wangzhe
wangzhe

Reputation: 615

Dynamic link with dlopen: symbol not found

I want to load my own dynamic link library for C++, here is my test code:

add.cpp

#include <vector>
using namespace std;
int add(int c)
{

    vector<int> v;

    int i;
    int sum = 0;
    for (i = 0; i < c; i++)
    {
        sum = sum + i;
    }
    return sum;
}

I execute the command as below to build the add.so:

g++ -fPIC -shared add.cpp -o add.so

Then I try to link it to my C++ project dynamically with dlopen:

main.cpp

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

typedef int (*add_func_ptr)(int);

    int main(int argc, char **argv)
{
    void *handle;
    double (*cosine)(double);
    char *error;

    handle = dlopen("./add.so", RTLD_LAZY);
    if (!handle)
    {
        fputs(dlerror(), stderr);
        exit(1);
    }

    add_func_ptr addfun;
    addfun = (add_func_ptr)dlsym(handle, "add");
    if ((error = dlerror()) != NULL)
    {
        fputs(error, stderr);
        exit(1);
    }

    printf("%d\n", (*addfun)(2));
    dlclose(handle);
}

Lastly, I compile it:

g++ main.cpp -ldl -o main

However, when I execute ./main, I always get the error: symbol not found.

There is a similar question, but the answer could not solve my problem. I know the issue may be caused by the name mangling in C++ but I don't know how to solve it, I want to use std::vector in the dynamic link, so I need to use C++ instead of c to build .so file.

Upvotes: 1

Views: 8444

Answers (1)

Most C++ implementations use name mangling (to encode some type information in the mangled name).

You need to declare extern "C" any symbol related to (i.e. used with) dlsym (this disables name mangling on that symbol).

So your add.cpp file should have the following declaration after its #include-s directives:

extern "C" int add(int c);

BTW, check with nm -D -C add.so the dynamic symbol table of your plugin.

Of course, an extern "C" function can use C++ features and types. So you could code

 extern "C" int sum_vector_elements(const std::vector<int> &v);
 int sum_vector_elements(const std::vector<int> &v) {
   int s =0;
   for (int x: v) { s += x; };
   return s;
 }

and do some dlsym(handle, "sum_vector_elements") in your main program.

See nm(1), dlopen(3), dlsym(3), C++ dlopen minihowto, Drepper's How To Write Shared Libraries, c++filt for more.

For readability reasons you might use typedef to define signatures (of dlsym-able functions in plugins) like here.

Upvotes: 4

Related Questions