usertype garbage_collect method not getting called
I'm trying to wrap a C interface with sol::usertype. For example, the zlib file-based API has a gzopen method that returns a gzFile and you close it (and free the memory) by calling gzclose. So I setup the open method as a sol::factory and the close method as the garbage_collect meta method. I am seeing the close method is never getting called.
Is it a bug or am I doing this wrong?
I'm using Lua 5.3 and sol 2.20.6 (my compiler does not support C++17).
Here's a nonsense example I worked-up on godbolt to demonstrate the problem. Obviously godbolt only has sol 3, but the same problem reproduces there, too. https://godbolt.org/z/f13Kbbn7n
This is the source:
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>
struct Foo
{
int bar;
};
Foo* foo_open()
{
auto* foo = new Foo();
std::cout << __func__ << " " << foo << std::endl;
return foo;
}
void foo_close(Foo* foo)
{
std::cout << __func__ << " " << foo << std::endl;
delete foo;
}
int main() {
sol::state lua;
lua.open_libraries();
lua.new_usertype<Foo>("Foo",
"new", sol::factories(&foo_open),
sol::meta_function::garbage_collect, sol::destructor(&foo_close)
);
lua.script("f = Foo.new()");
return 0;
}
This is the output:
ASM generation compiler returned: 0
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/crt1.o: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/libm.so.6: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/libmvec.so.1: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/libc.so.6: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
Execution build compiler returned: 0
Program returned: 0
foo_open 0x2f677860
Notice the foo_close method is not called.
From usertype memory:
sol does not take ownership of raw pointers, returned from functions or set through the set functions. Return a value, a
std::unique_ptr, astd::shared_ptrof some kind...
If you change the return value to a unique pointer, you can see the destructor being called: https://godbolt.org/z/669fGrEr4.
I think it's easiest if you return a std::unique_ptr with a custom deleter - something like std::unique_ptr<gzFile, gzglose>.
sol does not take ownership of raw pointers
I don't want sol to take ownership. I do want sol to call the garbage_collect method if one is provided. The garbage_collect method is never called and that's the part I think is a bug.
If you change the return value to a unique pointer... ...return a
std::unique_ptrwith a custom deleter...
This is what I was expecting to do as a work-around. I need to pre-wrap the C-library API before using it in the usertype definition. That's unfortunate.