-1

How can I call a method of an object knowing the address of the object and the address of the method(and its signature):

auto x = (int(*)())(&A::get_state)

Let the object be x of type void*.

So, using x and m, x of type void* and m of type int(*)()

Arnav Borborah
  • 11,357
  • 8
  • 43
  • 88
yonutix
  • 1,964
  • 1
  • 22
  • 51
  • 1
    Show your complete attempt and which line gives you an error. Hint: first you must cast the object pointer to the right type, if it is `void*` (I have no idea which is which now because your variables are all nondescriptive single letters). – John Zwinck Sep 08 '17 at 11:35
  • 1
    `&A::get_state` is probably not `int(*)()` but `int (A::*)() const`. – Jarod42 Sep 08 '17 at 11:37
  • There is no attempt because I don't know how should I do this. I can't pass the object parameter to the method, I can't do x->m because x is of type void* – yonutix Sep 08 '17 at 11:37
  • You are right Jarod. The point is that I try to load the class without knowing the type A – yonutix Sep 08 '17 at 11:37
  • Object is definitely not of type void* because void* did not have any member functions. :-) – Klaus Sep 08 '17 at 11:38
  • @Klaus x is of type void* because I loaded the constructor symbol using dlopen and dlsym and then I called the constructor which returned a void* – yonutix Sep 08 '17 at 11:39
  • Do you try to use some "generic C" function with type erasure `void foo(void (*)(void*), void* userData)` ? – Jarod42 Sep 08 '17 at 11:39
  • That cast is putrid. `&A::get_state` already has a type (likely address-of-member function), and you use the proper [member access operator](http://en.cppreference.com/w/cpp/language/operator_member_access) to invoke it, given a proper, *valid* object pointer. – WhozCraig Sep 08 '17 at 11:39
  • @Jarod42 yes, this is what I'm trying to do – yonutix Sep 08 '17 at 11:40
  • @WhozCraig, it is this way because I do a test, that is why I do the conversion – yonutix Sep 08 '17 at 11:40
  • If you know that you call a constructor via dlopen the type is of the constructed type and not void. So do a cast... look at http://tldp.org/HOWTO/C++-dlopen/thesolution.html#loadingclasses – Klaus Sep 08 '17 at 11:41
  • *"that is why I do the conversion"* - That isn't a conversion; it's a blatant *cast* to an improper type if `get_state` is a regular non-static member function (which we inconveniently cannot tell based solely on your post). – WhozCraig Sep 08 '17 at 11:43
  • 1
    Possible duplicate of [How to call through a member function pointer?](https://stackoverflow.com/questions/12189057/how-to-call-through-a-member-function-pointer) – nh_ Sep 08 '17 at 11:43
  • So you should show usage of the code and what you want to do. Not asking for a (unclear) sub-problem which is probably not the correct way. – Jarod42 Sep 08 '17 at 11:43
  • @nh_ It's not a duplicate because in that example the type is known – yonutix Sep 08 '17 at 11:43
  • @jarod42 I'll try to understand better the problem in order to put the right question – yonutix Sep 08 '17 at 11:44
  • 1
    You cannot call a member function on an object who's type you don't know. You have to cast your `void*` to that type first and then perform the call. If your actual type may vary, use an interface and cast to that. – nh_ Sep 08 '17 at 11:45
  • The question did not contain the underlaying problem: dlopen/generic void* C-stype pointers, and all the stuff around. Please provide a full example. The question in the current form is very bad! – Klaus Sep 08 '17 at 11:45
  • What's an "address" in C++? C++ has *pointers*, which are somewhat like addresses, but have associated *type* that indicates what they point to. – Toby Speight Sep 08 '17 at 14:50

1 Answers1

1

Since the question is quite unclear, I just blindly guess what you are trying to do and give a short explanation of how to do that.


Typically, plugin mechanisms using shared/dynamic libraries are implemented such that you have an interface.

class IPlugin
{
    virtual int doSomething() = 0;
};

Next, you implement this interface in your library and, in addition, provide a C function to create an instance of the implementation class (C function, because they are not name-mangled).

class MyPlugin : public IPlugin
{
    int doSomething() override { /* ... */ }
};

extern "C" 
{ 
    IPlugin* createPlugin() 
    { 
        return new MyPlugin{}; 
    }
}

Now, in your app you load the library using dlopen (or LoadLibrary on Windows) and fetch the address of your createPlugin function using dlsym (or GetProcAddress):

void* addr = dlsym(handle, "createPlugin");

Then, you cast this to the actual type, which is equivalent in all libraries:

auto createPlugin = reinterpret_cast<IPlugin*(*)()>(addr);

By calling createPlugin you can now create an instance of your concrete implementation and access it through the interface. There is no need for fetching any additional methods, since virtual member functions can be called directly across library boundaries (because of the vtable).

IPlugin* plugin = createPlugin();
int result = plugin->doSomething();

Same works for functions with arguments and different return types as well, of course. You should however export another C function to destroy the object instance again. delete should always be called by the library that created the object (since the library might have been built with a different implementation of new than the executable).

nh_
  • 2,211
  • 14
  • 24