GmodNET/GmodDotNet

[QUE] __gc not working with UserType? | Windows

JenyaRostov opened this issue · 11 comments

__gc metamethod in usertypes doesn't work at all

[ERROR] .NET Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at GmodNET.ManagedFunctionMetaMethods.ManagedDelegateExecutor(IntPtr lua_state) in D:\a\GmodDotNet\GmodDotNet\gm_dotnet_managed\GmodNET\ManagedFunctionMetaMethods.cs:line 31

To reproduce:
Push usertype
Create table, set its __gc field using PushManagedFunction
Set usertype's metatable to table created earlier
Push usertype to global table
Invoke __gc by doing something like GlobalUserdata = nil
???
Get exception

Maybe I'm doing something wrong. Though I'd like to hear how to do it correctly if that's the case!

@JenyaRostov can you provide a version of GmodDotNet you are using?

@JenyaRostov can you provide a version of GmodDotNet you are using?

Version 0.7.0-beta.2.32948499.better-xml-docs codename UstIlimsk

I'm creating usertype like this:

public class TestUserdataClass
{
    private int IntMember = 5;
}
public int __gcTestFunc(ILua lua)
{
    Console.WriteLine("GC\'ing!");
    return 0;
}

lua.PushSpecial(SPECIAL_TABLES.SPECIAL_GLOB);
GCHandle handl = GCHandle.Alloc(new TestUserdataClass());
lua.PushUserType(GCHandle.ToIntPtr(handl),130);
lua.CreateTable();
lua.PushManagedFunction(__gcTestFunc);
lua.SetField(-2,"__gc");
lua.SetMetaTable(-2);
lua.SetField(-2,"GUserdata");

Where did UserType index 130 come from?

Where did UserType index 130 come from?

Ah, just a random number I chose

This must not be a random number, but generated with Lua.CreateMetaTable (https://docs.gmodnet.xyz/api/GmodNET.API.ILua.html#GmodNET_API_ILua_CreateMetaTable_System_String__).

So in your case it must be something like this:

int type_id = lua.CreateMetaTable("MyType");
lua.PushManagedFunction(__gcTestFunc);
lua.SetField(-2, "__gc");
lua.Pop(1);
lua.PushUserType(GCHandle.ToIntPtr(handl), type_id);
...

Setting metatable for already created type is bad idea.

Here is how we use __gc metamethod for managed functions:

int managed_func_type_id = lua.CreateMetaTable("ManagedFunction");
unsafe
{
lua.PushCFunction(&ManagedFunctionMetaMethods.ManagedDelegateGC);
}
lua.SetField(-2, "__gc");
lua.Pop(1);

Maybe this will help you to figure out it a bit.

This must not be a random number, but generated with Lua.CreateMetaTable (https://docs.gmodnet.xyz/api/GmodNET.API.ILua.html#GmodNET_API_ILua_CreateMetaTable_System_String__).

So in your case it must be something like this:

int type_id = lua.CreateMetaTable("MyType");
lua.PushManagedFunction(__gcTestFunc);
lua.SetField(-2, "__gc");
lua.Pop(1);
lua.PushUserType(GCHandle.ToIntPtr(handl), type_id);
...

Setting metatable for already created type is bad idea.

Oh, it works now! Thank you very much, I was just doing it like I did in c++(setting TypeID manually)

Good! So your issue is resolved? May I close it?

Good! So your issue is resolved? May I close it?

Yep! Thanks again

Feel free to reopen the issue if you still have questions. You can also ask for help on our Discord server.