编译共享库
① 如何在C++中使用共享库的动态加载
一、先看看测试程序
1.库部分
hello.h
[cpp] view plain
在CODE上查看代码片派生到我的代码片
#ifndef ANDROID_Hello_H
#define ANDROID_Hello_H
class Hello_Base
{
public:
virtual ~Hello_Base() {};
virtual int setctl(int ctl) = 0;
virtual int getctl(int ctl) = 0;
};
class Hello : public virtual Hello_Base
{
public:
virtual ~Hello() {};
static Hello* Instance();
int setctl(int ctl);
int getctl(int ctl);
private:
static Hello* _instance;
int myctl;
};
extern "C" Hello_Base* CreatHello();
typedef Hello_Base* CreatHelloClass();
#endif
hello.cpp
[cpp] view plain
在CODE上查看代码片派生到我的代码片
#include "hello.h"
#include <stdio.h>
extern "C" Hello_Base* CreatHello(){
return Hello::Instance();
}
Hello* Hello::_instance = 0;
Hello* Hello::Instance()
{
printf("TK------>>>>>>Hello::Instance---------\n");
if(_instance == 0){
_instance = new Hello();
}
return _instance;
}
int Hello::setctl(int ctl)
{
printf("TK------->>>>>>setctl-----\n");
this->myctl = ctl;
return 1;
}
int Hello::getctl(int ctl)
{
printf("TK------->>>>>>getctl-----\n");
return this->myctl;
}
编译成动态链接库,一般要求PIC位置无关:
g++ -shared -fPIC -o libhello.so hello.cpp
生成:libhello.so
2.测试用例
test.cpp
[cpp] view plain
在CODE上查看代码片派生到我的代码片
#include "so/hello.h"
#include <stdio.h>
#include <dlfcn.h>
int main()
{
void* hello = dlopen("/home/lianxi/c++/ku/so/libhello.so", RTLD_LAZY);
if(!hello){
printf("dlopen /home/lianxi/c++/ku/so/libhello.so error!\n");
return -1;
}
dlerror();
CreatHelloClass* Creat_Hello = (CreatHelloClass*)dlsym(hello,"CreatHello");
const char* dlsym_error = dlerror();
if (dlsym_error) {
printf("error %s\n",dlsym_error);
return -1;
}
Hello_Base* mHello = Creat_Hello();
mHello->setctl(5);
int result = mHello->getctl(0);
printf("TK------>>>>>result is %d\n",result);
dlclose(hello);
return 1;
}
编译:g++ -o test test.cpp -L. -ldl
执行./test结果:
[plain] view plain
在CODE上查看代码片派生到我的代码片
TK------>>>>>>Hello::Instance---------
TK------->>>>>>setctl-----
TK------->>>>>>getctl-----
TK------>>>>>result is 5
二、分析
1.libdl库为C语言开发,当需要在C++中dlsym某个符号时、需要声明库中该符号为extern “C”,比如例子中的extern "C" Hello_Base* CreatHello();
2.由于不可能像C语言那样将C++类中的那么多方法都dlsym出来,这里使用了C++中对于纯虚类的实例化是运行时链接的特点;也就是说要在C++中对于类使用共享库的动态链接、必须定义一个纯虚的子类。
② 怎样编译加载共享库的可执行程序
1.下载FatJar插件2.安装之后,右键选择项目时,会出现BuildFatJar,选择该方法,然后按照向导即可一步步导出可执行jar文件。如果有外部的jar包,比如说sqljdbc.jar,则把所有要使用的第三方的jar包都复制到{java_home}\jre\lib\ext目录下。(必须重新启动Eclipse才能加载这些jar包)而象SWT项目这样所使用的jar包,则不需要这么设置,直接在向导中选择所需要的jar包即可。3.然后就可以在导出目录中运行这个可执行jar包,但如果是SWT项目,则必须在包含该可执行jar包的目录下有一个swt-win32-3235.dll之类的文件。4.有了可执行的jar文件,然后可以使用exe4j.exe之类的jar转exe软件,如果使用exe4j.exe则当调用到sqljdbc.jar之类的外部包时,则必须将sqljdbc.jar也一并导入。安装向导就可以生成exe文件了,如果是SWT项目则也必须在同目录下有swt-win32-3235.dll之类的文件。
③ gcc编译共享库怎么不报错
这只能说明一个问题,你依赖的库本身有问题,没有把它的依赖都加进去,也就是你例子中的①libb.so依赖liba.so;,你应该在生成libb.so的时候,把对liba.so的依赖加进去,这样应该就没有问题了。
④ 动态库(共享库)和静态库的区别,linux!!!
一个是程序编译的时候 相关函数就链接进去,加载到内存了。动态正好相反,现在在LINUX开发中很少用动态库,容易出问题
⑤ 编译GNU/Linux共享库,为什么要用PIC编译
不是共享库,而是动态库 (dynamic library)。 动态库的意思是库内的地址是在load时刻才由loader动态决定的,所以和静态库不同,编译出来的动态库代码必须是 “位置无关代码” (PIC: position-independant code),所以编译的时候必须加上 -fPIC 选项。
⑥ Android中静态库和共享库的区别
简单来讲:
静态库是在连接阶段直接拷贝到代码中使用的,而共享库是由加载器加载到内存,在运行时使用的。
编译出来的静态库(这里指jar包)里每个java文件对应的class文件都单独存在,可以直接导入Eclipse等IDE使用
而编译出来的共享库(jar包),内部是Android字节码Dex格式的文件,一般无法导入Eclipse等IDE使用。Android.mk中由BUILD_JAVA_LIBRARY指定生成共享BUILD_STATIC_JAVA_LIBRARY指定生成静态库。
⑦ Linux 下Makefile怎么写,编译包含 一个共享库文件,一个静态库文件,四个.c文件。
看看伟东山裸机的源代码就能知道了, 调用的库文件只需放在同一目录下就可以
⑧ 对于可执行的linux动态共享库,怎么传递命令行参数一般共享库没有main函数唉,就算自己定义了,
你本身的意图是什么?你可以在将命令行参数传递给你的程序本身,再通过函数调用传递给共享库文件不就好了么
⑨ 在一个版本的linux下编译的共享库so文件,在其它linux版本下可以正常使用吗
建议先核对下两个系统的GCC版本。