Dynamic loading without external "C"

I would like to use libdl to dynamically load C ++ in general. The problem is identifying the run-time characters that were named.

As described here, one solution is to remove the name using extern "C".

http://www.tldp.org/HOWTO/C++-dlopen/theproblem.html

This solution has the disadvantage of restricting dynamically loaded resources to C-style interfaces. Dynamically loaded functions cannot, for example, be overloaded functions.

What is a good way to overcome this limitation?

One possible solution would be a tool to label the mangle of the library source code with an accompanying function to get garbled names when you need to link the library. Does llvm provide tools for this?

Perhaps a clumsy solution would be a function that takes a function signature, creates dummy code with a function that has a signature, pipes to the compiler that was used with the flag to build the assembly, parses the output to retrieve the malformed name, and returns the changed name as a string. Then the string can be passed to dlsym ().

To make the problem concrete, here are two sample programs that illustrate something that the external β€œC” solution cannot dynamically load without changing the library code. The first dynamically links the library in traditional C ++ mode. The second uses dlopen. Linking an overloaded function in the first program is simple. There is no easy way to link an overloaded function in a second program.

Program 1: Dynamically Link Boot Time

main.cpp

// forward declarations of functions that will be linked
void say(int);
void say(float);

int main() {
    int myint = 3;
    say(myint);
    float myfloat = 5.0f;
    say(myfloat);
}

say.cpp

#include <iostream>

//extern "C" function signatures would collide

//extern "C" void say(int a) {
void say(int a) {
    std::cout << "The int value is " << a << ".\n";
}

//extern "C" void say(float a) {
void say(float r) {
    std::cout << "The float value is " << r << ".\n";
}

Output

$ ./main
The int value is 3.
The float value is 5.

Program 2: Dynamic Runtime Linking

main_with_dl.cpp

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

int main() {
    // open library
    void* handle = dlopen("./say_externC.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "dlopen error: " << dlerror() << '\n';
        return 1;
    }

    // load symbol
    typedef void (*say_t)(int);

    // clear errors, find symbol, check errors
    dlerror();
    say_t say = (say_t) dlsym(handle, "say");
    const char *dlsym_error = dlerror();
    if (dlsym_error) {
        std::cerr << "dlsym error: " << dlsym_error << '\n';
        dlclose(handle);
        return 1;
    }

    // use function
    int myint = 3;
    say(myint);
    // can't load in void say(float)
    // float myfloat = 5.0f;
    // say(myfloat);

    // close library
    dlclose(handle);
}

Output

$ ./main_with_dl
The int value is 3.

Compilation

Makefile

CXX = g++

all: main main_with_dl say_externC.so

main: main.cpp say.so
    $(CXX) -o $@ $^

main_with_dl: main_with_dl.cpp
    $(CXX) -o $@ $<

%.so : %.cpp
    $(CXX) -shared -o $@ $<

.PHONY: clean
clean:
    rm main main_with_dl say.so say_externC.so
+4
source share
1 answer

Mooing Duck , clang Visual Studio.

- , Visual Studio clang. __FUNCDNAME__ . , , , __FUNCDNAME__ mangle.

2, void say (int), void say (float).

Mooing Duck . main_with_dl.cpp, say.cpp .

http://coliru.stacked-crooked.com/a/7249cc6c82ceab00

clang++ -fms-extensions __FUNCDNAME__.

+2

Source: https://habr.com/ru/post/1543608/


All Articles