1

I have myLib.so file and USB.h header file. My header file looks like this and myLib.so contains implementation of this header file. How can I use myLib.so to call getUsbList function in my main.cpp.

#ifndef USB_H
#define USB_H
#include <string.h>
#include <string>
#include <vector>

vector<string> getUsbList();

#endif // USB_H

I try this but it gives error: Cannot load symbol 'getUsbList': myLib.so: undefined symbol: getUsbList

#include <iostream>
#include <dlfcn.h>
#include "USB.h"

int main() {
    using std::cout;
    using std::cerr;

    cout << "C++ dlopen demo\n\n";

    // open the library
    cout << "Opening myLib.so...\n";
    void* handle = dlopen("myLib.so", RTLD_LAZY);

    if (!handle) {
        cerr << "Cannot open library: " << dlerror() << '\n';
        return 1;
    }

    // load the symbol
    cout << "Loading symbol myLib...\n";
    typedef void (*USB_t)();

    // reset errors
    dlerror();
    USB_t getUsbList = (USB_t) dlsym(handle, "getUsbList");
    const char *dlsym_error = dlerror();
    if (dlsym_error) {
        cerr << "Cannot load symbol 'getUsbList': " << dlsym_error <<
            '\n';
        dlclose(handle);
        return 1;
    }

    // use it to do the calculation
    cout << "Calling getUsbList...\n";
    getUsbList();

    // close the library
    cout << "Closing library...\n";
    dlclose(handle);
}
dijkstra
  • 1,068
  • 2
  • 16
  • 39

1 Answers1

3

Looks like you're using C++

vector<string> getUsbList();

C++ applies so called "name mangling" to give each function symbol a unique name based on the types of its input and output parameters. This is done to support function overloading (multiple functions of the same name but with different parameter types).

You either have to load based on the mangled name or you have to disable name mangling (and hence the ability to overload the function).

Since there is no standard on how names are mangled and each compiler may implement it differently this is not a very robust method.

Disabling name mangling is done by surrounding the function declarations in the header with

extern "C" {

// ...

}
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • In case both executable and shared library are written in C++, extern "C" is not needed – Peter Petrik Feb 20 '14 at 14:21
  • 2
    @Peter: OP is trying to load the symbols using `dlopen`, passing in the unmangled name, which of course can not be found in the .so – datenwolf Feb 20 '14 at 15:00
  • How can I do that without using ldopen? – dijkstra Feb 20 '14 at 15:18
  • 1
    @dijkstra: Just link the library with the linker. Name the .so file `libmy.so` and link with `-lmy`, providing the library path with `-L` to the linker and use `-Wl,-rpath .` so that the executable linker looks for the library in the same directory as the executable is. See http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html for the details. – datenwolf Feb 20 '14 at 15:34