Linux上的C ++dynamic共享库
这是使用g ++进行dynamic共享库编译的后续步骤。
我想在Linux上用C ++创build一个共享类库。 我可以让库编译,我可以使用我在这里和这里find的教程来调用一些(非类)函数。 当我尝试使用库中定义的类时,我的问题就开始了。 我链接到的第二个教程显示了如何加载符号来创build库中定义的类的对象,但是停止使用这些对象来完成任何工作。
有谁知道一个更完整的教程来创build共享的C ++类库,也显示了如何在一个单独的可执行文件中使用这些类? 一个非常简单的教程,显示对象的创build,使用(简单的getter和setter将是好的),删除将是太棒了。 说明使用共享类库的一些开源代码的链接或引用同样适用。
尽pipecodelogic和nimrodm的答案确实起作用,但我想补充一点,自从问起这个问题之后,我就select了一个Linux 初始 编程的副本,第一章有示例C代码和很好的解释来创build和使用静态和共享库。 这些示例可以通过该书旧版本中的 Google图书search获得。
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 ); }
在Mac OS X上,编译时使用:
g++ -dynamiclib -flat_namespace myclass.cc -o myclass.so g++ class_user.cc -o class_user
在Linux上,编译时使用:
g++ -fPIC -shared myclass.cc -o myclass.so g++ class_user.cc -ldl -o class_user
如果这是一个插件系统,你将使用MyClass作为基类,并定义所有虚拟的function。 插件作者然后从MyClass派生,覆盖虚拟并实现create_object
和destroy_object
。 您的主应用程序不需要以任何方式进行更改。
下面显示了一个共享类库的共享示例[h,cpp]和一个使用该库的main.cpp模块。 这是一个非常简单的例子,makefile可以做得更好。 但它可以帮助你:
shared.h定义了类:
class myclass { int myx; public: myclass() { myx=0; } void setx(int newx); int getx(); };
shared.cpp定义了getx / setx函数:
#include "shared.h" void myclass::setx(int newx) { myx = newx; } int myclass::getx() { return myx; }
main.cpp使用这个类,
#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; }
和生成libshared.so的makefile以及与共享库链接的main:
main: libshared.so main.o $(CXX) -o main main.o -L. -lshared libshared.so: shared.cpp $(CXX) -fPIC -c shared.cpp -o shared.o $(CXX) -shared -Wl,-soname,libshared.so -o libshared.so shared.o clean: $rm *.o *.so
要实际运行“main”并链接到libshared.so,您可能需要指定加载path(或将其放在/ usr / local / lib或类似文件中)。
以下指定当前目录作为库的searchpath并运行main(bash语法):
export LD_LIBRARY_PATH=. ./main
要看到该程序与libshared.so链接,你可以尝试ldd:
LD_LIBRARY_PATH=. ldd main
打印在我的机器上:
~/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)
基本上,你应该在你想在共享库中使用类的代码中包含类的头文件。 然后,在链接时, 使用'-l'标志将您的代码与共享库链接。 当然,这需要.so是操作系统可以find它的地方。 见3.5。 安装和使用共享库
使用dlsym是因为在编译时不知道要使用哪个库。 这听起来不像这里的情况。 也许混淆的是,Windows调用dynamic加载的库是否在编译或运行时进行链接(使用类似的方法)? 如果是这样,那么你可以把dlsym认为是LoadLibrary的等价物。
如果你真的需要dynamic加载库(即它们是插件),那么这个常见问题应该有帮助。