編譯共享庫
① 如何在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版本。