The Pointer Assignment function works in C, but not C ++

I need to dynamically bind to a library function at runtime on Mac OS X. After the Apple example, I declare a pointer to a function and assign it with the result dlsym (). The following example compiles successfully as a simple C (.c) file. But I need this in a C ++ file, and if I compile this example as a C ++ file (.cpp), the clang compiler tells me

Cannot initialize variable of type 'void () (char *)' with rvalue of type 'void'

Why does it work in "C" and how can I fix it?

#include <dlfcn.h> void Test() { // Load the library which defines myFunc void* lib_handle = dlopen("myLib.dylib", RTLD_LOCAL|RTLD_LAZY); // The following line is an error if compiled as C++ void (*myFunc)(char*) = dlsym(lib_handle, "myFunc"); myFunc("Hello"); dlclose(lib_handle) ; } 
+6
source share
2 answers

dlsym returns void* . In POSIX (but not standard C, as James points out), there is an implicit conversion from void* to a function pointer type, so the purpose of myFunc just works. There is no implicit conversion in C ++ (because it is not type safe), so you need to tell the compiler that you really mean it by adding a cast:

 void (*myFunc)(char*) = (void(*)(char*))dlsym(lib_handle, "myFunc"); 

(or you can get fantasy with reinterpret_cast ).

+7
source

Because the C compiler is broken. There is no conversion (explicit or implicit) between void* and the function pointer, neither in C nor in C ++.

Posix adds a restriction on C and requires that void* and function pointers have the same size and presentation, so that:

 void (*myFunc)( char * ); *(void (**myFunc)( char* ))( &myFunc ) = dlsym(...); 

will work.

In C ++, you can use something like:

 class GetFunctionHelper; GetFunctionHelper getFunction( void* dlHandle, std::string const& functionName ); class GetFunctionHelper { void* fromSystem; freind GetFunctionHelper getFunction( void* , std::string const& ); GetFunctionHelper( void* fromSystem ) : fromSystem( fromSystem ) {} public: template <typename Ptr> operator Ptr() const { return *reinterpret_cast<Ptr const*>( &fromSystem ); } }; GetFunctionHelper getFunction( void* dlHandle, std::string const& functionName ) { return GetFunctionHelper( dlsym( dlHandle, functionName.c_str() ) ); } 

(with a bit more error checking, of course).

0
source

Source: https://habr.com/ru/post/946284/


All Articles