Advertisement

Need a little help with my shared library

Started by December 11, 2002 11:03 AM
4 comments, last by spiffgq 21 years, 9 months ago
I''m writing a shared library (aka "shared object" or "DLL" on Windows). I have been able to compile the library successfully and link to it in my application and run the application successfully. The problem I am having is that gcc is mangling the names of my functions in the library. This is preventing me from programmatically loading the functions at run time. Here is some example code. This first section is a test library. In this case, it is very simplistic, just to get the idea. testlib.cpp
  
#include <stdio.h>
void printNumber (int number){
   printf ("The number you want to print is \"%d\".\n", number);
   return;
}
  
I compile the source into an object file with the following command:

g++ -fPIC -c testlib.cpp
 
Then I compile the shared object with the following command:

g++ -shared -fPIC testlib.o -o libtestlib.so
 
Now, I have a viable shared object. If I create a header file with the function prototype (void printNumber (number)), then I can link a program to this library and run it like normal. For example:
  
#include "testlib.h"
int main () {
   printNumber (5);
   return 0;
}
  
This program will print:

The number you want to print is "5".
 
But that is not what I want to do. I want to be able to load my library programmatically at runtime. The following code demonstrates what I want to do:
  
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main () {

   void *handle;
   void (*print_num)(int);
   char *error;

   // Attempt to open the library

   handle = dlopen ("libm.so", RTLD_LAZY);

   // Error checking is omitted for clarity.

	
   // Load the cos function from the library.

   print_num = (void(*)(int))dlsym (handle, "printNumber");

   // If printNumber is not defined, print an error message here

	
   // Use the function

   (*print_num)(5);
   dlclose (handle);

   return 0;

}
  
I compile this program with the following command:

g++ -rdynamic -ldl main.cpp -o testProg
 
It compiles fine (no errors or warning). But when I run the program, I get an error:
quote: ./testProg: undefined symbol: printNumber
The reason printNumber is undefined is due to the compiler''s name mangling. When I looked at libtestlib.so in a hex editor, all occurrences of printNumber were _Z11printNumberi. When I looked at some of the standard c and c++ libraries (libm.so, libc.so, etc), the names of the functions were not mangled. So my question is how do I create my shared object so it doesn''t mangle the names? Thank you for your patience with my long windedness and for your help
SpiffGQ
Oh, some more notes:

The forum seems to be screwing up with my code''s formatting. Please overlook that.

Second, the error mentioned above did not crash the program. It was caused by this line:
print_num = (void(*)(int))dlsym (handle, "printNumber"); 

and I exited the program.
SpiffGQ
Advertisement
Well, when I try to load the function by using the compiled name, it works:

// print_num = (void(*)(int))dlsym (handle, "printNumber");print_num = (void(*)(int))dlsym (handle, "_Z11printNumberi"); 



But that introduces ugly portability problems. I still can''t figure out how to compile it w/o those name mangling problems. Any ideas? Thanks.
SpiffGQ
It is because I was using g++ and not gcc. If I use gcc, it works fine. That presents other problems, but I figured it out. Thanks for all your help

[edited by - spiffgq on December 11, 2002 6:54:46 PM]
SpiffGQ
i you want to use g++ you can just include everything in an
extern "C" { ... your code here ... } to prevent name mangling.

edit: maybe i wasn't too clear so what i mean is

    #include <stdio.h>extern "C" {    void printNumber (int number)    {        printf ("The number you want to print is \"%d\".\n",                 number);        return;    }}  


[edited by - necromancer_df on December 13, 2002 8:37:53 PM]
Thank you for your reply. The odd thing about extern "C" is the fact that you can still use c++ code:

extern "C"{void myfunc () {  MyClass *c = new MyClass;}} 

Works just fine
SpiffGQ

This topic is closed to new replies.

Advertisement