|
发表于 2008-7-1 16:52:21
|
显示全部楼层
原来楼主不是想要通过 dlopen 来动态加载 .so 啊.... sorry, 误解了, 而且把问题复杂化了.
为表歉意, 提供这个例子
- /* hello.h */
- #ifndef __HELLO_H__
- #define __HELLO_H__
- #include <iostream>
- using std::cout;
- using std::endl;
- class Hello {
- public:
- void fn(void) { cout << "hello" << endl; };
- };
- #endif//__HELLO_H__
复制代码
- /* hello.cpp */
- #include "hello.h"
- #if 1
- /* 只有当打算动态加载时才需要这一部分, 参见 bar.c */
- extern "C" void * get_interface(void)
- {
- return new Hello;
- }
- #endif
复制代码
为了把以上内容编译成库采用以下命令.
- # 编译成动态库
- g++ -Wl,-soname,libhello.so -shared -o libhello.so hello.o
- # 编译成静态库
- ar cru libhello.a hello.o
- ranlib libhello.a
复制代码
这样我们就得到了 libhello.so. 下面我们在 foo.c 中引用它
- /* foo.c */
- #include "hello.h"
- int main(void)
- {
- Hello * hello = new Hello;
- hello->fn();
- delete(hello);
- return 0;
- }
复制代码
编译时只要指定需要引用 libhello 即可, 与普通的库没有区别
- # 可以用绝对路径引用库
- g++ -o foo foo.o libhello.so
- # 如果 libhello.so 放在 /usr/lib 这样的系统路径中, 那么用下面的形式更好
- g++ -o foo foo.o -lhello
复制代码
另外既然已经提到了, 就再说一下动态加载的方法吧.
- /* bar.c */
- #include "hello.h"
- #include <dlfcn.h>
- int main(void)
- {
- void * handle = dlopen("./libhello.so", RTLD_LAZY);
- if (handle == NULL) {
- printf("dlopen(): %s\n", dlerror());
- return -1;
- }
- void * (* interface) (void) =
- (void * (*)(void)) dlsym(handle, "get_interface");
- Hello * hello = (Hello *) interface();
- hello->fn();
- delete(hello);
- return 0;
- }
复制代码
这次编译时不需要连接 libhello.so, 但是需要连接 libdl
foo 与 bar 的区别在于, 如果系统的库查找路径中找不到 libhello.so 的话, foo 是无法载入运行的, 而 bar 可以.
另外关于 extern "C", 这是为了使得接口编译后按照 C 语言形式, 因此我们才可能通过 get_interface 这个名字来对其进行查找, 如果按照 C++ 形式进行存储的话, 我们就无法直观地知道它编译后叫做什么名字了. |
|