intrusive_ptr.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include <iostream>
  2. extern "C"
  3. {
  4. #include "lua.h"
  5. #include "lauxlib.h"
  6. #include "lualib.h"
  7. }
  8. bool dostring(lua_State* L, const char* str)
  9. {
  10. if (luaL_loadbuffer(L, str, std::strlen(str), str) || lua_pcall(L, 0, 0, 0))
  11. {
  12. const char* a = lua_tostring(L, -1);
  13. std::cout << a << "\n";
  14. lua_pop(L, 1);
  15. return true;
  16. }
  17. return false;
  18. }
  19. #include <luabind/luabind.hpp>
  20. #include <boost/intrusive_ptr.hpp>
  21. namespace luabind
  22. {
  23. namespace converters
  24. {
  25. // tell luabind that there is a converter for boost::intrusive_ptr<T>
  26. template<class T>
  27. yes_t is_user_defined(by_value<boost::intrusive_ptr<T> >);
  28. template<class T>
  29. yes_t is_user_defined(by_const_reference<boost::intrusive_ptr<T> >);
  30. // function used to destruct the object in lua
  31. template<class T>
  32. struct decrement_ref_count
  33. {
  34. static void apply(void* ptr)
  35. {
  36. T* p = static_cast<T*>(ptr);
  37. intrusive_ptr_release(p);
  38. }
  39. };
  40. template<class T>
  41. void convert_cpp_to_lua(lua_State* L, const boost::intrusive_ptr<T>& ptr)
  42. {
  43. if (!ptr)
  44. {
  45. lua_pushnil(L);
  46. return;
  47. }
  48. T* raw_ptr = ptr.get();
  49. // add reference to object, this will be released when the object is collected
  50. intrusive_ptr_add_ref(raw_ptr);
  51. detail::class_registry* registry = luabind::detail::class_registry::get_registry(L);
  52. detail::class_rep* crep = registry->find_class(LUABIND_TYPEID(T));
  53. assert(crep != 0 && "You are trying to convert an unregistered type");
  54. // create the struct to hold the object
  55. void* obj = lua_newuserdata(L, sizeof(detail::object_rep));
  56. // we send 0 as destructor since we know it will never be called
  57. new(obj) luabind::detail::object_rep(raw_ptr, crep, detail::object_rep::owner, decrement_ref_count<T>::apply);
  58. // set the meta table
  59. detail::getref(L, crep->metatable_ref());
  60. lua_setmetatable(L, -2);
  61. }
  62. template<class T>
  63. boost::intrusive_ptr<T>
  64. convert_lua_to_cpp(lua_State* L, by_const_reference<boost::intrusive_ptr<T> >, int index)
  65. {
  66. typename detail::default_policy::template generate_converter<T*, detail::lua_to_cpp>::type converter;
  67. T* ptr = converter.apply(L, LUABIND_DECORATE_TYPE(T*), index);
  68. return boost::intrusive_ptr<T>(ptr);
  69. }
  70. template<class T>
  71. boost::intrusive_ptr<T> convert_lua_to_cpp(lua_State* L, by_value<boost::intrusive_ptr<T> >, int index)
  72. {
  73. return convert_lua_to_cpp(L, by_const_reference<boost::intrusive_ptr<T> >(), index);
  74. }
  75. template<class T>
  76. int match_lua_to_cpp(lua_State* L, by_value<boost::intrusive_ptr<T> >, int index)
  77. {
  78. typedef typename detail::default_policy::template generate_converter<T*, detail::lua_to_cpp>::type converter_t;
  79. return converter_t::match(L, LUABIND_DECORATE_TYPE(T*), index);
  80. }
  81. template<class T>
  82. int match_lua_to_cpp(lua_State* L, by_const_reference<boost::intrusive_ptr<T> >, int index)
  83. {
  84. typedef typename detail::default_policy::template generate_converter<T*, detail::lua_to_cpp>::type converter_t;
  85. return converter_t::match(L, LUABIND_DECORATE_TYPE(T*), index);
  86. }
  87. }
  88. }
  89. struct A
  90. {
  91. A()
  92. : cnt(0)
  93. {}
  94. ~A() { std::cout << "free memory\n"; }
  95. int cnt;
  96. };
  97. void intrusive_ptr_add_ref(A* ptr)
  98. {
  99. ++ptr->cnt;
  100. std::cout << "add ref\n";
  101. }
  102. void intrusive_ptr_release(A* ptr)
  103. {
  104. --ptr->cnt;
  105. std::cout << "release\n";
  106. if (ptr->cnt == 0) delete ptr;
  107. }
  108. void f(boost::intrusive_ptr<A> ptr)
  109. {
  110. std::cout << "count: " << ptr->cnt << "\n";
  111. }
  112. boost::intrusive_ptr<A> factory()
  113. {
  114. return boost::intrusive_ptr<A>(new A());
  115. }
  116. int main()
  117. {
  118. lua_State* L = lua_open();
  119. lua_baselibopen(L);
  120. luabind::open(L);
  121. using namespace luabind;
  122. module(L)
  123. [
  124. class_<A>("A")
  125. .def_readonly("cnt", &A::cnt),
  126. def("factory", &factory),
  127. def("f", &f)
  128. ];
  129. dostring(L, "a = factory()");
  130. dostring(L, "print('lua count: ' .. a.cnt)");
  131. dostring(L, "f(a)");
  132. lua_close(L);
  133. return 0;
  134. }