Search code examples
c++cdlopendlsym

Using C++ library from a C++ plugin loaded by a C app


I have a lib (.so) written in C++. If I do nm mylib.so I get 00000000000029a0 T _ZN4Bits7fromMemEPhl (among others).

On the other hand, I have an app written in C, that loads some plugins which are written in C++ (dlopen, dlsym, etc).

If I try to use my lib from my c++ plugin I get undefined symbol: _ZN4Bits7fromMemEPhl. Why?

EDIT:

This is how I compile my plugins:

$(PLUGINS_DIR)/%.so: $(PLUGINS_DIR)/%.o
    $(CXX) $^ -o $@ -shared

$(PLUGINS_DIR)/%.o: $(PLUGINS_DIR)/%.cpp
    $(CXX) -c $< -o $@ -g -Wall -std=c++11 -pedantic -lcpp-bitstring -fPIC -I.,-rpath=$(LIBS_DIR)/cpp-bitstring

And this is how I compile my main app:

$(TARGET): $(TARGET).o
    $(CC) -o $@ $^ -g -Wall -std=gnu99 -ldl -lcrypto -Wl,--export-dynamic

EDIT:

The problem is clear. For some reason my library (cpp-bitstring) isn't linked to my plugin. Where is the piece of code that I'm missing?


Solution

  • When you create your shared object, you have to provide the library dependencies if you want the libraries picked up when loading the plugin dynamically.

    Here is a simple Makefile:

    plugin.o:       CXXFLAGS += -fPIC
    main:   LDFLAGS += -ldl
    all:    main plugin.so
    
    plugin.so:      plugin.o
            $(CXX) $^ -o $@ -shared -lreadline
    

    The main.c file looks like:

    #include <dlfcn.h>
    #include <assert.h>
    
    int
    main (void)
    {
        void *p = dlopen("./plugin.so", RTLD_NOW);
        assert(p);
        void (*do_stuff)(void) = dlsym(p, "do_stuff");
        assert(do_stuff);
        do_stuff();
        dlclose(p);
        return 0;
    }
    

    And the plugin.cpp file looks like:

    #include <iostream>
    #include <stdlib.h>
    #include <readline/readline.h>
    
    extern "C" void do_stuff (void) {
        while (char *s = readline("> ")) {
            std::cout << "- " << s << std::endl;
            free(s);
        }
        std::cout << std::endl;
    }