最近公司在做微信端的定位和導(dǎo)航,所以需要云端提供導(dǎo)航和定位功能,為了復(fù)用之前客戶端的代碼,所以我需要把c文件編譯成linux下可以運(yùn)行的so庫(kù),記錄一下過(guò)程。
由于沒(méi)有搞過(guò),所以遇到問(wèn)題也不知道具體是哪里的問(wèn)題,所以就一路亂試。。。最后試了下,可以用。
用到的一些gcc命令
-shared:指定生成動(dòng)態(tài)連接庫(kù),不用該標(biāo)志外部程序無(wú)法連接。相當(dāng)于一個(gè)可執(zhí)行文件(我開始沒(méi)加這個(gè),報(bào)錯(cuò)找不到main)
-fPIC:表示編譯為位置獨(dú)立的代碼,不用此選項(xiàng)的話編譯后的代碼是位置相關(guān)的所以動(dòng)態(tài)載入時(shí)是通過(guò)代碼拷貝的方式來(lái)滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼段共享的目的。
-I:指定頭文件所在的文件夾
遇到的問(wèn)題
編譯時(shí)報(bào)錯(cuò):找不到j(luò)ni.h
我用虛擬機(jī)裝了Ubuntu,輸入java沒(méi)有找到,然后按著提示隨便裝了一個(gè)。。。
當(dāng)然我現(xiàn)在知道裝的是OpenJDK(OpenJDK和SunJDK的區(qū)別),google也決定在android N中使用OpenJDK了(相關(guān)報(bào)道)。。
所以我又下載了SunJDK,編譯的時(shí)候要引用相關(guān)文件,加如下命令
-I /[jdk目錄](méi)/include -I /[jdk目錄](méi)/include/linux
[jdk目錄](méi)/include是jni.h所在目錄;
[jdk目錄](méi)/include/linux是jni_md.h所在目錄
編譯報(bào)錯(cuò):找不到main
沒(méi)有加命令 -shared(命令介紹參考上面)
編譯時(shí)報(bào)錯(cuò):找不到math.h
使用math.h中聲明的庫(kù)函數(shù),gcc命令行必須加-lm選項(xiàng),因?yàn)閿?shù)學(xué)函數(shù)位于libm.so庫(kù)文件中(這些庫(kù)文件通常位于/lib目錄下),-lm選項(xiàng)告訴編譯器,我們程序中用到的數(shù)學(xué)函數(shù)要到這個(gè)庫(kù)文件里找。
我最后是把c文件一個(gè)一個(gè)編譯成.o然后,然后在編譯成.so的,因?yàn)榕鲁鲥e(cuò),不知道哪個(gè)文件的問(wèn)題。。。當(dāng)然也可以直接一句話如下:
gcc [.c文件,多個(gè)用空格隔開] -fPIC -shared -I /usr/xxx/include -I /usr/xxx/include/linux -lm -o libtest.so
多個(gè)c文件也可以使用 lib/*.c的方式
編譯成.o命令:gcc -c test.c
.o編譯成.so:gcc test.o -o test(默認(rèn)會(huì)添加lib前綴和.so后綴)