简体   繁体   中英

Mixing C/C++ code yields “undefined symbol” with shared library

This problem has perplexed me for a week now so I thought it might finally be time to ask you guys for help. Here is the story in a nutshell:

We are developing an embedded server in-house using Qt/C++. It is a very simple server that processes client requests and loads the proper function through dlopen()/dlsym() calls to do something vendor specific. This means the vendor would simply provide us a .so file in C with their function (which is transparent to us) the way we define. This would be written in C because of a lot of low level things it would need to do, and our server is in Qt because we plan on eventually having a frontend for it.

Here is some pseudocode:

In our main.cpp file (this is written in C fashion but uses the g++ compiler as is defined in the Qt mkspec, compiled using -ldl and -rdynamic to export all symbols):

  • dlopen() vendor.so file (tried with both RTLD_NOW and RTLD_LAZY)
  • dlsym() vendor.so init() method (this will call the vendor's init method, which will set up the name/properties of this "vendor plugin" through setter methods inside our code, call this plugin_set_name(args...))

In the shared header file (shared.h) (both code bases would use this; ours would have complete definitions of the structs, vendors would simply have prototypes of setters/getters):

  • extern "C" int plugin_set_name(args...)

In the vendor main.c file (compiled using gcc, -fPIC, and -shared)

  • Implementation of init() function as mentioned above

So essentially, what is happening is that the C++ code will use the dl calls to load the init() function from the C .so library, and then the C .so library will call a function that is defined in the C++ code (in this case, plugin_set_name). Is this even possible? Neither is linked against each other since they are compiled independently of each other and with different compilers (gcc vs g++).

The error I am getting is on runtime: "undefined symbol: plugin_set_name" (so it finds and gets inside the library's init() method just fine). It works flawlessly when I use gcc and straight C code to do everything so I know it's not the code but something with mixing C/C++. I also understand the use of extern "C" to prevent name mangling and have used nm / readelf to determine that there is no mangling of any kind. Any ideas? What is the best way to go about this?

Somehow, this just magically works today. I can't explain it. I simply have extern "C" declarations around the shared header, so in shared.h:

#ifdef __cplusplus
extern "C" {
#endif

plugin_set_name(args...)
other_shared_functions

#ifdef __cplusplus
}
#endif

I've always had this however. In either case, it works now with vendor plugins being compiled in C and server being compiled in Qt and C++. I think the problem was a combination of where to place all the externs as well as g++ linking flags (where rdynamic is crucial). Thanks. Just putting this here in case anyone else runs into the same issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM