Reputation: 119
I have an old static library that contains a simple simulator. The simulator is initiated by calling a function (sim) also included in the library. Now, I am trying to make this static library into a dynamic library:
g++ -shared -fPIC -o libdynamicSimulator.so -Wl,--whole-archive libstaticSimulator.a -Wl,--no-whole-archive
The object files in ./libstaticSimulator.a are also compiled with the -fPIC flag. This step works fine with no compiler/linker error. I followed a SO post for this step.
However, I encountered linker error when I tried to test the shared library by calling the sim function from a main:
g++ -O2 -g -m64 -Wall -fno-strict-aliasing -c -o main.o main.c
g++ -O2 -g -m64 -Wall -fno-strict-aliasing -L. main.o -o sim_dynlib -ldynamicSimulator -lm -lpthread
main.o: In function `main':
main.c:40: undefined reference to `sim(unsigned long*, unsigned long*, unsigned long*, unsigned long)'
collect2: error: ld returned 1 exit status
make: *** [sim_dynlib] Error 1
I used nm to verify that the symbol is there in the dynamic library:
$ nm ./libdynamicSimulator.so | grep sim
0000000000102e10 T sim
The library is written in C++ but sim's name is not mangled because it is defined within a extern "C" block:
extern "C" {
uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len)
{
...
}
}
Here is how the main.c is declaring and using the function:
extern uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
int main(int argc, char **argv)
{
... // preparing a1, a2, a3, len
uint64_t act_sum = sim(a1, a2, a3, len);
...
}
I have been googling for hours trying to find the problem but all I could find was about reordering the -l's in the g++ command line, which I already did -- -ldynamicSimulator after main.o.
I feel that I am missing something really simple/stupid here but for the life of me, I could not figure out what it is.
Any help or comment is appreciated.
Upvotes: 0
Views: 657
Reputation: 119
I have figured it out. My feeling was correct -- it is a stupid mistake:
The declaration of the sim() function in main.c needs to be put into a extern "C" block, since I am using g++ as the compiler.
extern "C" {
extern uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
}
int main(int argc, char **argv)
{
... // preparing a1, a2, a3, len
uint64_t act_sum = sim(a1, a2, a3, len);
...
}
The linker error is gone after this change.
Another shorter declaration that works:
extern "C" uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
Upvotes: 1