1

I'm designing a plugin system using shared library. It works as follow: a plugin base class is provided as a template with virtual functions, and its header file includes all dependencies those plugin would need; plugin developers need to override those virtual functions to fulfill their targets, using only dependencies of the plugin system; the main executable includes header file of plugin base class to inherit dependencies. The main executable runs as a loop and it could load shared library in runtime (using dlopen), and a singleton called 'PluginManager' will call functions in loaded plugins once per frame.

A simple example below:

// plugin.h

#include "third_party/test.pb.h" // which is not used in main executable, but in one of the plugins

#include "basic/math/math_util.h" // which is used in main executable

class Plugin {
 public:
  Plugin() = default;
  virtual ~Plugin() {}
  virtual void Execute() {}
};
// do_something.h
// It has a do_something.cc, but we omit it here since it's not so important
#include "plugin.h"

class DoSomething : public Plugin {
 public:
  DoSomething() : Plugin() {}
  ~DoSomething() {}

  virtual void Execute() override; // It will do something using data structures and functions described in test.pb.h and math_util.h
 private:
  test::TestBody test_; // described in test.pb.h
};

// main.cc
#include "plugin.h"

int main(int argc, char** argv) {
 int should_continue = 1;
 while (should_continue) {
   // Do something about dlopen, and call Execute() in plugins after loaded.
 }
}

In this little example, the plugin DoSomething is using functions from math_util.h, which is also used by our main executable, and functions from test.pb.h, which is included by main executable but not used. The compiling works nicely, but when loading DoSomething plugin, it will throw dlerror() like

Can't open handle: /opt/ourprogram/plugins/libdo_something.so: undefined symbol: _ZTIN4test8TestBodyE

I understand that it's an expected behavior, since our main executable don't have a reason to really export this symbol. If I remove usage of TestBody in DoSomething plugin, or add a simple instancing in main executable like test::Testbody body, the shared library could be loaded as a charm.

The thing is, it's a plugin system and we don't want users to mess up with our core code except for including something, not to mention in our entry file. Is there any easy way for us to make the plugin work? Any help would be appreciated.

Feej
  • 11
  • 1
  • As the error says there is an undefined symbol at loading the TestBody function, it might be interesting to show us the part where you load it with dlsym. Also, do check this tutorial on dlopen if you haven't already, it might help : https://tldp.org/HOWTO/C++-dlopen/intro.html – Hykosit Oct 13 '22 at 11:23

1 Answers1

0

Is there any easy way for us to make the plugin work?

Yes: use -rdynamic or (if your linker supports it) --export-dynamic-symbol when linking your main binary.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362