2

I am creating sheared object and opening using dlsysm() but I am getting the following error:

error: invalid conversion from "void*" to "void (*)()"

Here is my code:

#include<iostream>
#include<dlfcn.h>
using namespace std;

int main() {
    void (*fnptr)();
    void *handle;

    handle = dlopen("./libtestshared.so",RTLD_LAZY);
    if (!handle) {
        cerr << "Cannot open library: " << dlerror() << '\n';
    } else {
        cout<<"Opening"<<'\n';
    }

    fnptr = dlsym(handle , "fun");

    return 0;
}
MSalters
  • 173,980
  • 10
  • 155
  • 350
Yugandhar
  • 33
  • 7
  • can you please provide the code where you get the error? hard to see what is going on here – Stefano Mar 22 '17 at 12:33
  • #include #include using namespace std; int main() { void (*fnptr)(); void *handle; handle = dlopen("./libtestshared.so",RTLD_LAZY); if (!handle) { cerr << "Cannot open library: " << dlerror() << '\n'; } else { cout<<"Opening"<<'\n'; } fnptr = dlsym(handle , "fun"); return 0; } – Yugandhar Mar 22 '17 at 12:35
  • ok... i have added the code formatted for you... – Stefano Mar 22 '17 at 12:49
  • waiting it to be peer reviewed.... – Stefano Mar 22 '17 at 12:49
  • 1
    And this is not a C++11 questions... i will propose to retag this – Stefano Mar 22 '17 at 12:58
  • @Stefano `` and namespaces are definitely C++. – Quentin Mar 22 '17 at 13:16
  • 1
    @Stefano also, why did you sneakily modify the code while editing? Your edit had invalidated the question... – Quentin Mar 22 '17 at 13:19
  • how did i invelidate the question?... if this was done was by mistake... – Stefano Mar 22 '17 at 13:37
  • oh yes... you are right! – Stefano Mar 22 '17 at 13:38
  • 1
    @Stefano look at the edit history. you replaced `void (*fnptr)();` with `void *fnptr;`. And please edit your comments... It's not whatsapp... – JHBonarius Mar 22 '17 at 13:38
  • This question comes up quite frequently; a simple solution is: `fnptr = (void (*)())(intptr_t)dlsym(handle , "fun");` Some people will argue this based on the fact that on some platforms code-pointers might be bigger than data-pointers. But on these platforms you cannot use `dlsym` either. – Lorinczy Zsigmond Mar 22 '17 at 14:12
  • Added back the C++11 tag, because it's exactly this cast which led to the introduction of "conditionally supported behavior" in C++11. – MSalters Mar 22 '17 at 14:13

3 Answers3

4

As dlsym can return a pointer to a function of any signature, its designers chose to return an opaque void*. Of course, dlsym works under the assumption that such a void* can then be safely converted to the correct function pointer type. This is done as follows:

auto fnptr = reinterpret_cast<void(*)()>(dlsym(handle , "fun"));
Quentin
  • 62,093
  • 7
  • 131
  • 191
  • Only, you made the answer C++11 by adding the `auto` keyword ;) – JHBonarius Mar 22 '17 at 13:33
  • @J.H.Bonarius What do you mean? – Quentin Mar 22 '17 at 13:34
  • The `auto` keyword was not added until C++11. Although the TS is probably using a new compiler, older ones will not support it. In the case of the TS, he already defined `fnptr`earlier (c-style ;) ), you could even leave it out in your answer. – JHBonarius Mar 22 '17 at 13:37
  • 2
    @J.H.Bonarius the question was originally tagged [c++11]. In any case, there's no reason for SO answers to be bloated with retrocompatibility with a fifteen-year old standard unless explicitly requested (by using the [c++03] tag). – Quentin Mar 22 '17 at 13:50
  • @J.H.Bonarius: You need C++11 anyway, because in C++98 this was illegal. – MSalters Mar 22 '17 at 14:14
3

A void * is not compatible with a function pointer.

A cast is required in this case:

fnptr = (void (*)())dlsym(handle , "fun");
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Although correct, this is c-style casting. I think Quentin's answer is better from a C++ perspective. See [link](http://www.cplusplus.com/doc/tutorial/typecasting/). – JHBonarius Mar 22 '17 at 14:00
  • when i am calling the fnptr segmentation fault is happened. 0x080487d8 in main () at sampledlopen.cpp:21 fnptr = 0 handle = 0xa048020 – Yugandhar Mar 23 '17 at 12:00
  • @Yugandhar Your fnptr is zero (ie. null) so you're calling a null pointer. – Paul Belanger Jan 19 '18 at 14:50
  • @JHBonarius Indeed https://stackoverflow.com/questions/7831696/reinterpret-cast-vs-c-style-cast However this is still working nicely and provide compatibility with C in this very specific case – Antonin GAVREL Apr 16 '20 at 15:30
0

I have never used dlsym but here what his manpage says:

The function dlsym() takes a "handle" of a dynamic library returned by dlopen() and the null-terminated symbol name, returning the address where that symbol is loaded into memory.

So what it return is not a function pointer but a standard pointer! Something as follow should work:

void* returnedAddress = dlsym(handle , "fun");
fnptr = reinterpret_cast<void(*)()>(returnedAddress);
Stefano
  • 3,981
  • 8
  • 36
  • 66
  • This is not what the TS wants: he deletes his own comment, but he expects the returned address to be a function pointer. So the 'undefined' pointer (imho there is no such thing as a "standard" pointer) needs to be cast to the correct type. – JHBonarius Mar 22 '17 at 13:43
  • i have modified my code void* returnedAddress = dlsym(handle , "fun"); fnptr = reinterpret_cast(returnedAddress); but i am getting segmentation fault. by analyzing core handle=0(i.e #1 0x080487d8 in main () at sampledlopen.cpp:23 fnptr = 0x8048418 handle = 0x0 returnedAddress = 0x82ee020 ) – Yugandhar Mar 23 '17 at 04:17