C++ Dynamic Shared Library on Linux C++ Dynamic Shared Library on Linux linux linux

C++ Dynamic Shared Library on Linux


myclass.h

#ifndef __MYCLASS_H__#define __MYCLASS_H__class MyClass{public:  MyClass();  /* use virtual otherwise linker will try to perform static linkage */  virtual void DoSomething();private:  int x;};#endif

myclass.cc

#include "myclass.h"#include <iostream>using namespace std;extern "C" MyClass* create_object(){  return new MyClass;}extern "C" void destroy_object( MyClass* object ){  delete object;}MyClass::MyClass(){  x = 20;}void MyClass::DoSomething(){  cout<<x<<endl;}

class_user.cc

#include <dlfcn.h>#include <iostream>#include "myclass.h"using namespace std;int main(int argc, char **argv){  /* on Linux, use "./myclass.so" */  void* handle = dlopen("myclass.so", RTLD_LAZY);  MyClass* (*create)();  void (*destroy)(MyClass*);  create = (MyClass* (*)())dlsym(handle, "create_object");  destroy = (void (*)(MyClass*))dlsym(handle, "destroy_object");  MyClass* myClass = (MyClass*)create();  myClass->DoSomething();  destroy( myClass );}

On Mac OS X, compile with:

g++ -dynamiclib -flat_namespace myclass.cc -o myclass.sog++ class_user.cc -o class_user

On Linux, compile with:

g++ -fPIC -shared myclass.cc -o myclass.sog++ class_user.cc -ldl -o class_user

If this were for a plugin system, you would use MyClass as a base class and define all the required functions virtual. The plugin author would then derive from MyClass, override the virtuals and implement create_object and destroy_object. Your main application would not need to be changed in any way.


The following shows an example of a shared class library shared.[h,cpp] and a main.cpp module using the library. It's a very simple example and the makefile could be made much better. But it works and may help you:

shared.h defines the class:

class myclass {   int myx;  public:    myclass() { myx=0; }    void setx(int newx);    int  getx();};

shared.cpp defines the getx/setx functions:

#include "shared.h"void myclass::setx(int newx) { myx = newx; }int  myclass::getx() { return myx; }

main.cpp uses the class,

#include <iostream>#include "shared.h"using namespace std;int main(int argc, char *argv[]){  myclass m;  cout << m.getx() << endl;  m.setx(10);  cout << m.getx() << endl;}

and the makefile that generates libshared.so and links main with the shared library:

main: libshared.so main.o    $(CXX) -o main  main.o -L. -lsharedlibshared.so: shared.cpp    $(CXX) -fPIC -c shared.cpp -o shared.o    $(CXX) -shared  -Wl,-soname,libshared.so -o libshared.so shared.oclean:    $rm *.o *.so

To actual run 'main' and link with libshared.so you will probably need to specify the load path (or put it in /usr/local/lib or similar).

The following specifies the current directory as the search path for libraries and runs main (bash syntax):

export LD_LIBRARY_PATH=../main

To see that the program is linked with libshared.so you can try ldd:

LD_LIBRARY_PATH=. ldd main

Prints on my machine:

  ~/prj/test/shared$ LD_LIBRARY_PATH=. ldd main    linux-gate.so.1 =>  (0xb7f88000)    libshared.so => ./libshared.so (0xb7f85000)    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e74000)    libm.so.6 => /lib/libm.so.6 (0xb7e4e000)    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7e41000)    libc.so.6 => /lib/libc.so.6 (0xb7cfa000)    /lib/ld-linux.so.2 (0xb7f89000)


Basically, you should include the class' header file in the code where you want to use the class in the shared library. Then, when you link, use the '-l' flag to link your code with the shared library. Of course, this requires the .so to be where the OS can find it. See 3.5. Installing and Using a Shared Library

Using dlsym is for when you don't know at compile time which library you want to use. That doesn't sound like it's the case here. Maybe the confusion is that Windows calls the dynamically loaded libraries whether you do the linking at compile or run-time (with analogous methods)? If so, then you can think of dlsym as the equivalent of LoadLibrary.

If you really do need to dynamically load the libraries (i.e., they're plug-ins), then this FAQ should help.