I'm reading through the manpage for dlopen and friends on FreeBSD. I'm working on a cross-platform application that is using shared libraries for loadable plugins. I've never done this before, but I think I have a decent grasp of how it works. The manpage mentions dlsym(), which appears to be the common means of getting a function pointer from a shared library, and dlfunc(), which supposedly avoids compiler complaints about casting a void* to a function pointer. Is there a reason dlsym() is more common (portability?) ? I'm wondering whether I should use dlfunc() to avoid compiler problems, or use dlsym(). Is dlfunc() portable?
You can't expect to have a dlfunc
provided on other UNIXes, but it's implementation is straightforward and portable. You can do something like
# configure.ac
AC_SYSTEM_EXTENSIONS
AC_CHECK_FUNCS([dlfunc])
// some common header
#include "config.h"
#ifndef HAVE_DLFUNC
/* copied from FreeBSD, source/include/dlfcn.h */
struct __dlfunc_arg {
int __dlfunc_dummy;
};
typedef void (*dlfunc_t)(struct __dlfunc_arg);
dlfunc_t dlfunc(void *restrict handle, void *restrict symbol);
#endif
// some source file
#include "config.h"
#ifndef HAVE_DLFUNC
/* copied from FreeBSD, lib/libc/gen/dlfunc.c */
dlfunc_t dlfunc(void *restrict handle, void *restrict symbol) {
union {
void *d;
dlfunc_t f;
} rv;
rv.d = dlsym(handle, symbol);
return rv.f;
}
#endif
if you are using Autoconf, and other build+configuration systems probably have similar abilities. (dlsym
is much more widely available.)
That being said, I think the compiler warning is silly – the C standard does not, but POSIX guarantees that void *
pointers can safely represent all function pointers…