Advertisement

Registering pointers to class functions without asMETHOD

Started by June 10, 2005 10:10 AM
2 comments, last by WitchLord 19 years, 5 months ago
I'm currently trying to register class methods thru an interface (virtual table) to the engine script (because the engine script implementation can be any scripting engine, not necessarily AngelScript). For this reason I cannot use asMETHOD macro since the class of the function cannot be sent thru the interface. Now, one method could be to register with asCALL_CDECL_OBJFIRST (or OBJLAST) and use an additional function to encapsulate the real class function. But this will mean 2 function calls. I've read thru the AngelScript code and I saw the asSMethodPtr template that it is used by asMETHOD macro in order to cope with different platforms specifics. From what I understand all I need is a method to send the proper member function pointer and its correct size to the scripting engine. It seems that the size of the pointer is variable from one compiler/platform to another (for Visual C++ it seems to always be 4 bytes, the offset from “this” pointer). What I do is use the following function in the engine script interface:

void ScriptEngine::RegClassMbrFunc(const char *class_name, const char *decl, 
     const void *pnt_to_func_pnt, const size_t func_pnt_size)
{
   asUPtr func_ptr;
   asMemClear(&func_ptr, sizeof(func_ptr));
   asMemCopy(&func_ptr, pnt_to_func_pnt, func_pnt_size);

   angel_script_engine->RegisterObjectMethod(class_name, decl, 
      func_ptr, asCALL_THISCALL);
}

This function receives the pointer to the function pointer and its size and constructs the asUPtr without the use of the asMETHOD macro. One possible usage is:

   typedef void (MyClass::*class_func)();
   class_func p = (class_func)&MyClass::ClassFunc;
   script_engine->RegClassMbrFunc("MyClass", 
     "void f(string &in)", &p, sizeof(p));

What I need to ask is: Is this a portable (working for all platforms) solution? And second, why is the pointer size variable from one compiler to another? Is it not the offset from the “this” pointer (and always 4 bytes)? If this is a portable solution maybe you will consider adding it to the angel script interface as an additional method of registering class functions (with parameters: pointer to function pointer and pointer function size). Regards Adrian Licu Quad Software
Hi,

I cannot say if your solution is portable or not. It would seem to be basically the same thing that I do with asFUNCTION() and asMETHOD(), but it is possible that in converting the method pointer to void* you risk loosing some vital information, if the compiler lets you do that conversion at all.

The pointer size is not just variable between compiler to compiler, it can even be variable within the same compiler. Visual C++ uses 5 different sizes for method pointers, ranging from 4 to 20 bytes, depending on the type of the class and wether the compilation is for a 32bit processor or a 64bit processor.

For 32bit processors:

- normal class method: 4 bytes, the pointer points to the function implementation
- virtual class method: 4 bytes, the pointer points to a function stub that reads the virtual function table and jumps to the true function implementation
- virtual class method with multiple inheritance: 8 bytes, a function pointer, and an offset to the true virtual function table
- virtual class method with virtual inheritance: 12 bytes, a function pointer, and an offset to the true virtual function table, plus another offset to find the true object. One needed value is missing from this pointer type, since the MSVC++ compiler hardcodes it when the method is invoked
- class method for an unknown implementation: 16 bytes, the same as the virtual inheritance pointer, except that the missing value is now included.

On 64bit processors, an additional 4 bytes are needed, since all pointers are 64bit.

On GNUC the method pointer is always 8 bytes in size independently of the class type (I would think it is 12 bytes on 64bit processors but cannot say for sure). And they manage to keep all the important information in those 8 bytes. They use a trick where the least significant bit of the function pointer shows wether it is an address or an offset in the vftable.

If you are interested in more details, there is a really interesting article on the code project that explains everything you need: Member Function Pointers and the Fastest Possible C++ Delegates

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement
Hi Andreas,

Thanks for all the information, I really appreciate it.

About converting to void*, I'm not converting the function pointer, but a pointer to the pointer function ;) which is always a normal pointer.

Regards
True! :)

The only problem with that is that you first need store the pointer in a variable, in order to take the pointer to the pointer.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement