Reputation: 623
So, I have a following example I'm trying to run.
header.h
extern "C" {
void registerfunc();
};
main.cpp
#include "header.h"
#include <dlfcn.h>
#include <iostream>
using namespace std;
typedef void (*register_func)();
void registerfunc() {
cout << "register func has been called" << endl;
}
int main() {
void* lib_handle = dlopen("./test/test.so", RTLD_NOW | RTLD_GLOBAL);
if(lib_handle == NULL){
cout << "no such lib:" << dlerror() <<endl;
return 0;
}
register_func reg = (register_func)dlsym(lib_handle, "test");
if(reg == NULL){
cout << "Cannot load symbol" << dlerror() << endl;;
} else {
reg();
}
return 0;
}
it is compiled with following makefile
all:
g++ main.cpp -ldl
then, i want to use registerfunc from my own so, which is written in the following way:
main.h:
extern "C"
{
void test();
};
main.cpp
#include "main.h"
#include "../header.h"
void test() {
registerfunc();
}
Makefile:
all:
g++ main.cpp -fPIC -shared -o test.so
When I compile it this way and run a.out (output of first main), I get:
no such lib: ./test/test.so: undefined symbol: registerfunc
However, if i compile a.out and test.so using following commands:
a.out -> g++ -g -fPIC -shared main.cpp -ldl
test.so -> g++ -g main.cpp -fPIC -shared -o test.so ../a.out
then I'm getting a segmentation fault with following backtrace (gdb -ex run a.out):
0x0000000000000001 in ?? ()
That leaves me kinda stumped, as to how make test.so call something that is defined by it's callee. Could you, please, help?
Upvotes: 1
Views: 1519
Reputation: 213879
You have at least three separate problems here:
The smaller one is that you have two files named main.cpp
, and it's not entirely clear which command refers to which file in your question.
The bigger problem is that you are expecting test.so
to bind to registerfunc
in a.out, but the function is not exported from a.out
unless some shared library participating in the link references that function, or you link with -Wl,--export-dynamic
(which exports all functions). This is the real solution.
You can see which functions are exported from your a.out
with this command:
nm -D a.out | grep ' T '
Finally, when you do this:
a.out -> g++ -g -fPIC -shared main.cpp -ldl
you are actually creating a shared library (named a.out
), not an executable. Running such a shared library as if it were an executable leads to the crash you've observed.
Upvotes: 2