-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)();
laalto
  • 150,114
  • 66
  • 286
  • 303
  • how did symbols for the member function end up in the shared object? when I try to do that, non-virtual member function symbols are not published. – Dima Tisnek Mar 21 '14 at 09:51

4 Answers4

2

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
  • 51,233
  • 8
  • 91
  • 143
  • 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 Jun 30 '10 at 13:35
  • 1
    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 Jun 30 '10 at 14:43
1

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
  • 95,107
  • 10
  • 109
  • 188
  • 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 Jun 30 '10 at 13:40
  • I think you might be wrong, Mark. Lallato has 2 pointers. Given a pointer to instance and an address of member function is it quite possible to call member function on an instance. It is clearly non-trivial for virtual function and possible even non-virtual functions defined in a class that has virtual functions. Non-virtual function on a plain class should be easy, however portable application still requires knowledge or the type in some compilers. I'll cook up an example in GCC which is easiest. – Dima Tisnek Mar 21 '14 at 09:14
0

According to the answer below it is doable in GCC, but not portable:

https://stackoverflow.com/a/5067992/705086

Community
  • 1
  • 1
Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120
0

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.
  • 55,948
  • 11
  • 128
  • 197