[C++, ASM] Calling member functions of unknown type

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • unauthorized
    New Member
    • May 2009
    • 81

    #1

    [C++, ASM] Calling member functions of unknown type

    The short story:
    I need to be able to cast a function pointer for any function and class to an intermediate type, so I could call it from any point of my program using the "__asm call" instruction.


    The long story:
    I have been trying to develop a data driven method to call C++ functions, that allows calling them with minimal overhead. The final goal is to be able to call any function, by knowing just what kind of parameters to send to it.

    Now, I immediately figured out that C/C++ don't have a mechanism that allows such behavior without raising template hell, so after some research I came up with the following chunks of code:

    Code:
    // Call a non-member/static function:
    void(*func_ptr)(int, int) = &myFunc;
    
    __asm {
    	push b		; // 2nd parameter
    	push a		; // 1st parameter
    	call func_ptr
    	add esp, 8 	; // more accurately it's sizeof(int)*2
    }

    Code:
    // Call a memer function:
    myClass ob;
    void(myClass::*mem_ptr)(int, int) = &myClass::myMemFuc;
    
    __asm {
    	push b		; // 2nd parameter
    	push a		; // 1st parameter
    	lea ecx, [ob]
    	call mem_ptr
    	; no need to unwind the stack for some reason that is beyond me
    }

    Now, the above code has been working great and I thought I had nailed it, but while putting the whole thing together, something unexpected happened:

    Code:
    void* pFunc = func_ptr; // ok, works great with call
    void* pMem = mem_ptr; // compiler error 2440 in Visual Studio
    After some more researching on the matter, I found out that function pointers are not actual pointers, but contain additional data (for virtuality, etc...) which explains why casting to a normal pointer would not be allowed.
    However, what puzzles me the most is how call mem_ptr is allowed on a non-pointer. The call instruction should only work on a memory address, right?
    I looked at the disassembly, but there were no signs of the code being expanded any further (other than a jmp right after the call, which the compiler probably kept for vtable handling).

    I tried going over the C++ specification but to no avail. Google couldn't help me either.

    So my question is this: how do I convert mem_ptr to an arbitrary data type, that can later be called without the actual function prototype (just abstract pointers to the func and class, and knowledge of the parameter).

    The idea behind all this is to allow me to assign a unique identifiers during compilation, which I would then use to translate into pointers during runtime and be able to repeatedly call the said functions with minimal overhead.

    I realize the implications of throwing away C++'s type safety out of the window, but the benefits far out weight the risks in my situation.

    Any thoughts on this would be greatly appreciated.
  • RRick
    Recognized Expert Contributor
    • Feb 2007
    • 463

    #2
    What about the "this&quot ; pointer?

    Pointers to class member functions need a class object to generate a this value. I don't see any mention of one and this (no pun intended) might be the problem.

    Take a look at the following link. It mentions issues with type mismatch compiler errors.


    Hope this helps.

    BTW: If you don't get a satisfactory answer here, you might do better at one of the specific news groups for C++ (i.e. comp.lang.c++). They have been able to answer some pretty esoteric questions for me.

    Comment

    • unauthorized
      New Member
      • May 2009
      • 81

      #3
      The instruction "lea ecx, [ob]" is loading the object address into the ecx register, which is what my compiler did when I was looking at a normal function call.
      Shame on me for using such obscure naming!

      Anyway, I figured out how to get the actual function pointer a few minutes ago:

      Code:
      void** ppVoid = (void**) &myClass::myFunc; // This is black magic a.k.a. undefined behavior.
      void* pActualPtr = *ppVoid;
      Using "call pActualPtr", properly calls the required function on the right object. Now hopefully, I can get this to work with gcc and under 'nix...

      Comment

      Working...