How to decouple exported characters from C ++ in dynamic libraries in Xcode on OSX

I am trying to create a dynamic C ++ library that can be loaded at boot time. I finally got his job, but he's a little ugly. I have a function that takes a pointer to a C ++ class as an argument, which looks like this:

bool registerGrindPlugin( Grind::PluginManager* mgr ); 

But of course, it is exported as:

 _Z19registerGrindPluginPN5Grind13PluginManagerE 

I tried the .c file with a simple function and it was exported as "registerGrindPlugin", but of course I cannot pass the C ++ class as an argument in this way.

Su ... my question is: is there a way to untie or an alias of the exported character so that I don't have to use a monster like Z19registerGrindPluginPN5Grind13PluginManagerE in my dlsym call?

I saw something about -alias_list as a linker option, but I didn't quite understand how to use it in Xcode. If this is a solution, can someone provide more details on how to use this?

+4
source share
3 answers

Typically, plugin interfaces are defined using naming conventions and calls. The name mangling potentially depends on the compiler (non-standard).

So, the easiest way is to define some interface function and declare that as extern "C" :

 extern "C" { bool registerGrindPlugin( Grind::PluginManager* mgr ); } 

You may need to replace Grid :: PluginManager with void * and an internal application. It should be a simple structure, not a class with virtual functions.

If you insist on working with malformed names, you can take a look at the source code for 'C ++ filt', which is a gnu utility that is also available on OS X.

+2
source

The way you try to do this will not work in the long run.

You cannot count on any specific C ++ anti-aliasing / damping algorithm. Different compilers - and even different versions of the same compiler - used different ones. That way you can do this and upgrade to the new version of Xcode and stay in a bad situation.

In addition, C ++ suffers from the Fragile Binary Interface problem. To avoid this, all operations with the internal components of the Grind :: PluginManager instance, from creation to access to a member for deletion, must be performed in the same dynamic library.

Solving these problems is one of the reasons for the Objective-C messaging system and Windows OLE.

A C ++ solution should use a wrapper system.

First, you need to define an opaque pointer type to stand in Grind :: PluginManager *. Cocoa C-language bindings do this a lot.

 typedef void* MyGrindPlugInManagerOpaqueHandle; 

Secondly, for every operation you want to do in Grind :: PluginManager from outside the dynamic library, you need to use extern "C" to define a function with indestructible C-binding and which takes one of these opaque pointers as an argument. For instance:

 #ifdef __cplusplus extern "C" { #endif void foo_wrapper(MyGrindPlugInManagerOpaqueHandle *bar); #ifdef __cplusplus } #endif 

Thirdly, the implementation in the C ++ file will look something like this:

 void foo_wrapper(MyGrindPlugInManagerOpaqueHandle *bar) { Grind::PluginManager* baz = (Grind::PluginManager*)bar; baz->foo(); } 
+4
source

You can set the linker flags in Xcode by selecting the target that you are trying to build in the left pane of the project window and clicking the "Information" button. The build tab has a whole section of linker settings, including one called "Other linker flags"; this should allow you to specify any linker options you want to try.

+1
source

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


All Articles