Embedding Lua in C++ mixed with C
I am working on embedding Lua in a C++ project, which relies heavily on some legacy C code. I have a few questions regarding to garbage collection and variable scope.
Here are some snippets related to the questions that follow:
/* C side */
typedef struct
{
/* fields */
} Element;
typedef struct
{
void * m_elems
unsigned int size;
} Container;
// C API for managing Container and Element
....
int allocContainer(Container*, unsigned int);
void freeContainer(Container*);
Element * getElemByIndex(unsigned int);
// C++ side
struct ElementWrapper
{
private:
Element m_elem;
public:
/* field accessors (NO modifiers) */
};
class ContainerWrapper
{
private:
ContainerWrapper m_cntnr;
public:
ContainerWrapper(int N); // allocates space for N elements
~ContainerWrapper();
// stack alloc'ed variable
ElementWrapper getElementAtIndexStackAllocated(unsigned idx) const;
// heap alloc'ed variable
ElementWrapper * getElementAtIndexHeapAllocated(unsigned idx) const;
};
-- Lua side
wrapper = Container:new(10)
for i =1,10 do
-- get the ith element
el_s = wrapper.getElementAtIndexStackAllocated(i)
el_h = wrapper.getElementAtIndexHeapAllocated(i)
-- do something with retrieved element ..
end
- when are variables el_s and el_h garbage collected?
- Do I need to use the 'local' keyword for el_s and/or el_h to make sure that variables are discarded at the end of each iteration in the 'for' loop?
- Indices start from 0 in C/C++ world, but 1 from Lua side - do i need to be aware of this in my code, or does tolua++ glue code manage this for me?
Note: I am intentionally, not using smart pointers (like boost:shared_ptr), because the C library handles all of the memory allocation/deallocation etc, and since I dont know when the Lua garbage collector kick in, all of the wrapper classes I expose to Lua (via tolua++), contain raw C style pointers as private members. They are not deleted when the exposed C++ class is harvested by the Lua GC. This way, the C library will delete the mem as and when needed, b开发者_运维百科y itself - and there is no danger of dangling pointers - which may be the case if I use shared pointers or some other smart pointer with reference counting which may get confused by the Lua GC activities (hope you get the gist - though I know this last bit is not very clear). Bottom line, I am using raw ptrs for a good reason.
In Lua, elements that are no longer referenced are garbage collected (at the proper time).
This means that el_h
and el_s
will be considered for garbage collection whenever you will overwrite them, you don't need to make them local
.
In other words, the object you'll get for el_h
when i
= 1 will be marked for being garbage collected when you will assign to el_h
the object you'll get for i
= 2.
I assume tolua++ will handle the metatables so that destructors are called whenever the object will be garbage collected, I've never used it as I always found easier to write binding code for C or C++ functions by hand.
I would be surprised, though, if tolua++ would scale the index for you, it has no clue it should do that. You should pass the same argument to wrapper.getElementAtIndexStackAllocated()
in Lua that you would do in C++.
Note that I've used "marked for being garbage collected". The actual time the garbage collection will happen depends on different factors and, in general, is not a good idea to be dependant on this. However you can force a garbage collection using collectgarbage("collect")
精彩评论