1

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.

Biffen
  • 6,249
  • 6
  • 28
  • 36
wangzhe
  • 573
  • 1
  • 5
  • 13
  • I can't understand what you are talking about. You are trying to compile a c++ project or to create your own lib file? – Yves Mar 09 '18 at 06:16
  • OK, you are trying to load the dynamic lib. If you get the error `symbol not found`, you can try to not use `dlopen`, which means to try to load the `so` file in static way. If you still get the same error, it means that the `add.so` file doesn't your processor, the `add.so` may come from ARM whereas you are using it on a X86 processor. – Yves Mar 09 '18 at 06:26
  • Thanks but I want to send name of .so file from parameter and then use dlopen load and run it. different .so file have same function name but different implementation. How to do that if I not use dlopen? – wangzhe Mar 09 '18 at 06:33
  • The problem is, your code looks like good, but it did make an error. So you have to figure out why. What I was telling you is to help you figure out why. You've never mentioned where the `add.so` came from, so I supposed that you were using a wrong-format lib file. – Yves Mar 09 '18 at 06:41
  • You must make sure that the `add.so` is the right format, then we can move on. – Yves Mar 09 '18 at 06:42
  • I use this command to build add.so : g++ -fPIC -shared add.cpp -o add.so, and source code of add.cpp is listed in question:#include using namespace std; int add(int c) { vector v; int i; int sum = 0; for (i = 0; i < c; i++) { sum = sum + i; } return sum; } – wangzhe Mar 09 '18 at 06:46
  • Your question should mention the error given by `dlerror()` at runtime – Basile Starynkevitch Mar 09 '18 at 08:42
  • @wangzhe: never comment your own question, but edit it to improve it – Basile Starynkevitch Mar 09 '18 at 11:43
  • Thanks a lot for your help:) @ Basile Starynkevitch – wangzhe Mar 09 '18 at 14:46

1 Answers1

3

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.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thanks a lot for your help and patience instead of posting some useless comments like somebody above:) , I also got this [link](https://www.tldp.org/HOWTO/html_single/C++-dlopen/#thesolution), it seems that even if I use extern c, I still could use c++ feature? – wangzhe Mar 09 '18 at 07:04