Home > Archive > Unix Programming > July 2007 > How to call dlopen() and dlsym() properly?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
How to call dlopen() and dlsym() properly?
|
|
| Rouben Rostamian 2007-07-25, 7:07 pm |
| From the man page for the function dlsym() we see that
it has the prototype:
void *dlsym(void *handle, const char *symbol);
It opens a dynamic library pointed to by "handle", finds
the address of the function pointed to by "symbol" and
returns the address. Therefore I call it like this:
double (*myfunc)(double); /* the prototype of myfunc may vary */
myfunc = dlsym(handle, symbol);
The problem is, "gcc -Wall -ansi -pedantic" complains:
main.c:28: warning: ISO C forbids assignment between
function pointer and ‘void *’
I see that. But I don' see a way around it.
The compiled program seems to work correctly. I may even make
the warning go away if I drop the "-pedantic". But still it bothers
me that this code goes against the standard. So my quetion is:
What is the proper way to call dlsym()?
--
Rouben Rostamian
| |
| Rainer Weikusat 2007-07-25, 7:07 pm |
| Rouben Rostamian <"Rouben Rostamian"@not.a-real-address.net> writes:
> void *dlsym(void *handle, const char *symbol);
[...]
> double (*myfunc)(double); /* the prototype of myfunc may vary */
> myfunc = dlsym(handle, symbol);
>
> The problem is, "gcc -Wall -ansi -pedantic" complains:
>
> main.c:28: warning: ISO C forbids assignment between
> function pointer and âvoid *â
>
> I see that. But I don' see a way around it.
>
> The compiled program seems to work correctly. I may even make
> the warning go away if I drop the "-pedantic". But still it bothers
> me that this code goes against the standard. So my quetion is:
> What is the proper way to call dlsym()?
The 'proper way to use dlsym' is not to expect that functionality
beyond the ISO-C-standard is necessarily compatible with it. You may
not even convert a void * to a function pointer by explicit casting
(6.3.2.3|1). There is actually a way to make this 'formally legal',
but I doubt you will like it:
myfunc = (double (*)(double))(intptr_t)dlsym(handle, symbol);
(you may convert the void * to 'any integer' and 'any integer to any
pointer', with the specifics being implementation defined, AFAIK).
| |
| Eric Sosman 2007-07-25, 7:07 pm |
| Rouben Rostamian wrote On 07/25/07 13:10,:
> From the man page for the function dlsym() we see that
> it has the prototype:
>=20
> void *dlsym(void *handle, const char *symbol);
>=20
> It opens a dynamic library pointed to by "handle", finds
> the address of the function pointed to by "symbol" and
> returns the address. Therefore I call it like this:
>=20
> double (*myfunc)(double); /* the prototype of myfunc may vary */
> myfunc =3D dlsym(handle, symbol);
>=20
> The problem is, "gcc -Wall -ansi -pedantic" complains:
>=20
> main.c:28: warning: ISO C forbids assignment between
> function pointer and =E2=80=98void *=E2=80=99
>=20
> I see that. But I don' see a way around it.
>=20
> The compiled program seems to work correctly. I may even make
> the warning go away if I drop the "-pedantic". But still it bothers
> me that this code goes against the standard. So my quetion is:
> What is the proper way to call dlsym()?
Try
myfunc =3D (double (*)(double)) dlsym(handle, symbol);
(A typedef may make the reading easier.) This makes the
conversion from void* to function pointer explicit, and may
shut the compiler up. "May," because the compiler is always
permitted to whine about anything it wants to, even perfectly
legal code.
... which this isn't, going strictly by the rules of C.
C's abstract machine does not assume that code and data are
addressed the same way, so as far as C is concerned function
pointers and data pointers have nothing to do with each other.
When you use something like dlsym() you are relying on the
ability to convert between these (supposedly) dissimilar
pointers. The ability is there on any system where dlsym()
exists (otherwise it couldn't work at all), but gcc doesn't
know that you're compiling for "casual Friday C" instead of
for "Sunday best C." (In fact, "-pedantic" specifically asks
to be held to a high standard of purity.)
If the cast won't silence the compiler, you may need to
drop "-pedantic" -- which would be a shame, because the flag
will help you catch other problems in the code. But it's
not your fault; dlsym() is an API that necessarily goes
beyond what C guarantees.
--=20
Eric.Sosman@sun.com
| |
| Frank Cusack 2007-07-26, 4:18 am |
| most interesting
| |
| Rouben Rostamian 2007-07-26, 10:05 pm |
| Thank you, Eric and Rainer for your comments regarding
the usage of dlsym(). Either of your suggestions:
myfunc = (double (*)(double)) dlsym(handle, symbol);
myfunc = (double (*)(double))(intptr_t)dlsym(handle, symbol);
silences "gcc -Wall -ansi -pedantic", at least in the
version of gcc that I am using.
--
Rouben Rostamian
| |
| Rainer Weikusat 2007-07-27, 4:17 am |
| Rouben Rostamian <"Rouben Rostamian"@not.a-real-address.net> writes:
> Thank you, Eric and Rainer for your comments regarding
> the usage of dlsym(). Either of your suggestions:
>
> myfunc = (double (*)(double)) dlsym(handle, symbol);
> myfunc = (double (*)(double))(intptr_t)dlsym(handle, symbol);
>
> silences "gcc -Wall -ansi -pedantic", at least in the
> version of gcc that I am using.
The theoretical difference is that the behaviour of the direct cast to
a function pointer is undefined. There is no technical reason which
would prevent it from working (or at least none that I know of), but
you run the practical risk that some clown will in future decide that
not translating the assignment to machine code could be called 'an
optimization' and since the behaviour was undefined to begin with,
you'll just get what you deserve. It wouldn't be the first time for
this to happen.
|
|
|
|
|