1

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?

Jack
  • 361
  • 2
  • 4
  • 17
  • I think that you should read this : http://stackoverflow.com/questions/2744181/how-to-call-c-function-from-c – Jean-Baptiste Yunès Feb 23 '15 at 19:53
  • I've already prepended the relevant functions with extern "C" (which is what that example shows) and it still does not work. I also took Qt out of the equation by compiling manually outside of it using g++ and I have the same problem. – Jack Feb 23 '15 at 20:08

1 Answers1

2

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.

Jack
  • 361
  • 2
  • 4
  • 17