views:

132

answers:

3

What's the best way to call a member function if you have an object and a bare function pointer pointing to the member? Essentially I want to call the function pointer with thiscall calling convention.

Background: I'm looking up symbols in a shared library dynamically, obtaining a factory function pointer and a pointer to a certain member function I want to call. The member function itself is not virtual. I have no control over the shared library, I just have the binary.

Example:

typedef void * (*GenericFptr)();
GenericFptr lookup(const char *);

class CFoo;

GenericFptr factoryfn(lookup("CFoo factory function"));
CFoo *foo = reinterpret_cast<CFoo *>(factoryfn());

GenericFptr memberfn(lookup("CFoo member function"));

// now invoke memberfn on foo

Currently I'm using an union to convert the function pointer to a pointer to member function. It's ugly and creates dependencies to compiler implementation details:

class CFoo {
  public: 
  void *dummy() { return 0; }
};
typedef void * (CFoo::*FooMemberPtr)();

union {
  struct {
    // compiler-specific layout for pointer-to-member
    void *x, *y;
    GenericFptr ptr;
  } fnptr;
  FooMemberPtr memberfn;
} f;

f.memberfn = &CFoo::dummy; // init pointer-to-member
f.fnptr.ptr = memberfn;    // rewrite pointer

void *result = (foo->*f.memberfn)();
+2  A: 

A pointer to member function can't be stored in a pointer to function because it needs more information (for instance in case of multiple inheritance an offset may have to be applied to this before the call). So you can't do without knowledge of implementation details.

If you want to be portable, the easiest is for your library to provide wrapper functions doing the member call.

AProgrammer
Thanks. I know enough implementation details to make the union trick work but I'd like not need to do so. I cannot touch the library itself as it is already deployed to hundreds of millions instances.
laalto
Would adding a second library which provides the wrapper be acceptable? The problem as you formulate it has no standard solution, so you have to change your approach. Without knowing the whole context, it is quite difficult to propose things.
AProgrammer
A: 

The following two links provide insight and possibly a solution. Note that calling a member function pointer with a this argument usually don't work, since you must take into account virtual methods, multiple and virtual inheritance.

http://www.codeproject.com/KB/cpp/FastDelegate.aspx

http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx

Alexandre C.
+1  A: 

Unfortunately a member function pointer has more information than a standard function pointer, and when you get the standard function pointer, converting it to a member function pointer would effectively be trying to generate extra data out of thin air.

I don't think there's any portable way to do what you're attempting, although if the union appears to work you could probably get away with that. Again, you would need to know the representation and calling convention for these methods for each compiler you wish to use to build the bode.

If you know the member function's name, why can't you just do foo->dummy() for example? Otherwise either the lookup function needs to provide a full member function pointer or the library would have to provided a C wrapper interface with normal functions to which a this pointer can be passed.

Mark B
Thanks. Calling the function directly is not an option as I cannot link to the library at compile time. Also the lookup function is provided by the underlying operating system and cannot easily be replaced.
laalto