g++ 生成C++ .so庫文件,並調用示例


Tags: g++ C++ so library

 

在Linux系統下用g++命令編譯C++程序.也可以生成so,a鏈接庫

 

示例一 編譯時鏈接so庫

Test.h 文件內容

 

Main.cpp文件內容

 

命令執行過程

 

//生成so文件

g++ -shared -fPIC -o libTestLib.so Test.h

 

//編譯Main.cpp並鏈接so.生成可執行文件Main

g++ Main.cpp -o Main -L.

 

//執行可執行文件Main

./Main

 

 

使用Makefile

 

 

Makefile解讀

Makefile的基本規則是

生成目標 : 依賴目標

<TAB>命令

Makefile會首先檢查生成目標依賴目標,若所有依賴目標准備好,則執行下一行以<TAB>(制表符)開頭的命令,來產生生成目標.

一般來說一個Makefile只有一個最終目標(一般是Makefile定義的第一個).而這個目標可以依賴其他目標,Makefile會自動檢查依賴,並且按依賴關系逐個生成

上面Main目標依賴LibTest.so Main.cpp,其中Main.cpp是源文件,不需要生成,而LibTest.so是一個目標,因此Makefile會找到LibTest.so的生成規則,並首先生成LibTest.so再生成最終目標Main

LibTest.so的生成又依賴於Test.h文件,其中Test.h是源文件,所以可以直接利用下面的<Tab>后的命令生成LibTest.so.因此Makefile首先執行的是g++ -shared -fPIC -o LibTest.so Test.h

在生成LibTest.so后,最終目標Main的所有依賴文件已經准備好,則Makefile執行

g++ Main.cpp -o Main -L.

來生成最終目標Main文件

偽目標

Mainfile中的clean也是一個目標,但是並不依賴於任何文件,這種目標稱為偽目標,而且應該用

.PHONY: clean

來聲明該偽目標.

Makefile的執行:

對於Makefile的最終目標(一般為第一個),可以直接在命令行執行make命令,由Makefile自動識別來執行

也可以使用

make 目標名

來執行指定目標,而對於偽目標clean,則必須使用 make clean的方式顯示執行:

make clean

 

參考

http://blog.csdn.net/haoel/article/details/2887

 

注意:

 

-shared 是指生成動態鏈接庫,詳細查Google

http://blog.sina.com.cn/s/blog_54f82cc201011op1.html-fPIC 是指編譯代碼為可共享,參考:

-o 后面為輸出文件名稱

-L. 是指的在以下位置查找鏈接庫,其中L后面的(.)是指的是當前目錄

 

 

示例二 代碼動態加載庫

若要動態加載.so庫則需要使用dlopen 等函數

目錄結構

Test.h內容

extern "C" {

int TestAdd(int x, int y);

}

 

Test.cpp內容

#include "Test.h"

 

extern "C" int TestAdd(int x, int y)

{

return x + y;

}

 

Main.cpp內容

#include <dlfcn.h>

#include <iostream>

using namespace std;

 

int main(int argc, char *argv[])

{

void *handle = dlopen("./Test.so", RTLD_LAZY);

if (!handle)

{

cout << dlerror() << endl;

return -1;

}

typedef int (*add_t)(int a, int b);

add_t add = (add_t) dlsym(handle, "TestAdd");

if (!add)

{

cout << dlerror() << endl;

dlclose(handle);

return -1;

}

int a = add(3,5);

cout << "a = " << a << endl;

dlclose(handle);

return 0;

}

 

Makefile內容:

Main: libTest.so Main.cpp

g++ -ldl -o Main Main.cpp

 

libTest.so: ./Sources/*.cpp

g++ -shared -fPIC -o libTest.so ./Sources/*.cpp -I ./Headers/

 

.PHONY: clean

 

clean:

-rm -f Main

-rm -f libTest.so

 

 

注意:

1.

不管什么庫文件,你都既要在包含.h文件(不然編譯通不過:有未聲明的函數),也要在gcc選項里面指定.so文件的位置(不然鏈接通不過:未知的符號) 比如 gcc -I include_path -L lib_path -lyourlib include_path改成你頭文件的目錄 lib_path改成你動態庫文件的目錄 -lyourlib 改成l加上你要引用的庫文件名字 比如libpthread.so就改成-lpthread

http://blog.chinaunix.net/uid-21273878-id-4148042.html

 

 

示例三 Linux下Eclipse 中調用so文件

 

 

首先在Linux下安裝Eclipse,確保jdk環境都配置ok

創建Eclipse工程,創建java代碼源文件

TestLib.java

public class TestLib {

static{

System.loadLibrary("Test");

}

public static native int TestAdd(int a, int b);

public static void main(String args[])

{

System.out.println(TestAdd(1, 2));

}

}

在TestLib.java文件目錄下,使用javac命令生成TestLib.class文件

javac TestLib.java

在bin目錄下,找到生成的TestLib.class 文件(若沒有該文件,則在TestLib.java相同目錄下找,並復制到bin目錄下.

在bin目錄下,執行以下命令生成C++工程使用的TestLib.h文件

javah -classpath . -jni TestLib

 

生成的TestLib.h

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class TestLib */

 

#ifndef _Included_TestLib

#define _Included_TestLib

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: TestLib

* Method: TestAdd

* Signature: (II)I

*/

JNIEXPORT jint JNICALL Java_TestLib_TestAdd

(JNIEnv *, jclass, jint, jint);

 

#ifdef __cplusplus

}

#endif

#endif

 

創建C++代碼Test.cpp,實現TestLib.h中定義的各接口:

Test.cpp

include "TestLib.h"

 

JNIEXPORT jint JNICALL Java_TestLib_TestAdd

(JNIEnv *env, jclass cls, jint a, jint b)

{

return a + b;

}

 

編寫Makefile

Makefile 內容

libTest.so: ./Sources/*.cpp

g++ -shared -fPIC -o libTest.so ./Sources/*.cpp -I ./Headers/ \

-I /usr/lib/jvm/java-1.7.0-openjdk.x86_64/include \

-I /usr/lib/jvm/java-1.7.0-openjdk.x86_64/include/linux

 

命令行執行 make libTest.so

生成libTest.so文件,將so文件拖到Eclipse項目中.運行Eclipse項目.

正確調用libTest.so中定義的接口

 

 

注意:

生成的TestLib.h包含了jni.h文件,而且需要jni_md.h文件.所以在g++命令時,需要用 -I 參數指定這兩個頭文件的路徑

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM