linuxjna呼叫so動態庫

白展糖發表於2012-12-11

文中提到:為什麼命名為libtest.so而不是test.so呢?因為jna在找so檔案的時候,要匹配字首為lib的so檔案

http://zhenaihua0213.blog.163.com/blog/static/50887766201129104611955/
在linux下使用jna呼叫本地方法的時候,需要將C寫成的程式編譯為so檔案

1、寫一個簡單test.c檔案:

#include<stdio.h>
int add(int a,int b);
int add(int a,int b)
{
 
    int c = a+ b ;
 
    return c;

 2、編譯為so動態連結庫:
gcc的預設路徑是在ROOT下,如果你是用ROOT許可權登陸的話。

 gcc -fpic -c test.c

gcc -shared -o libtest.so test.o

ls看一下生成的檔案:

libtest.so test.c test.o

這樣就會生成so檔案了。 這裡為什麼要命名為libtest.so而不是test.so呢?因為jna在找so檔案的時候,要匹配字首為lib的so檔案

3、接下來開始寫java檔案(需要下載jna.jar),我們寫一個TestSo.java:

 import com.sun.jna.Library;
import com.sun.jna.Native;
public class TestSo {
public interface LgetLib extends Library {
// 呼叫linux下面的so檔案,注意,這裡只要寫test就可以了,不要寫libtest,也不要加字尾
LgetLib INSTANCE = (LgetLib)Native.loadLibrary(“test”,LgetLib.class);
int add(int a,int b);
}
public int add(int a,int b){
return LgetLib.INSTANCE.add(a,b);
}
public static void main(String[] args) {
TestSo ts = new TestSo();
int c = ts.add(10,20);
System.out.println(“10+20=”+c);
}
}

  4、 接下來進行編譯:

export CLASSPATH=$CLASSPATP:./jna.jar     
 
      
 
     //這裡是設定環境變數

javac TestSo.java

這裡直接執行TestSo的話:

 java TestSo
Exception in thread “main” java.lang.UnsatisfiedLinkError: Unableto load library `test`: libtest.so: cannot open shared object file:No such file or directory
atcom.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163)
atcom.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236)
atcom.sun.jna.Library$Handler.<init>(Library.java:140)
at com.sun.jna.Native.loadLibrary(Native.java:379)
at com.sun.jna.Native.loadLibrary(Native.java:364)
atTestSo$LgetLib.<clinit>(TestSo.java:7)
at TestSo.add(TestSo.java:11)
 
at TestSo.main(TestSo.java:15)

這個錯誤是指找不到so檔案。於是我們將so檔案所在的目錄設定到環境變數LD_LIBRARY_PATH中:

vim /etc/profile

在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC下面加入

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${你的so目錄}

之後,你可以檢查一下設定的起沒起效果:echo$LD_LIBRARY_PATH,如果出現你設定的內容就對了,如果沒有,你可以重新開啟一個視窗再查一下

設定好環境變數之後,你就可以執行java類了:

java TestSo
10+20=30

到此執行成功。

如果你遇到了緊急的情事,而這個地方又搞不定,你可以暫時交so檔案放到/usr/lib這個目錄下面,一般是可以使程式執行的。

 關於路徑,這個確實頭痛,在WINDOWS下還好辦,Native.loadLibrary(String,class)第一個引數用絕對路徑沒有問題,如下:

我專案位置:D:workspace est
.java檔案位置:D:workspace estscrcomsysang

CLASSPATH=.;%JAVA_HOME%libdt.jar;%JAVA_HOME%lib ools.jar;%TOMCAT_HOME%commonlibservlet-api.jar;%JAVA_HOME%jrelib
t.jar

Java code
API INSTANCE
= (API)Native.loadLibrary(D:\測試程式\DLL\API,API.class);

相對路徑的話,如下:

放在工程的src下,釋出後出現在WEB-INFclasses下,然後在你要呼叫API INSTANCE =(API)Native.loadLibrary的類中(如類名為A),呼叫如下
String path=A.class.getResource(“/”).getPath()+”API.dll”;
//如何tomcat路徑中有空格,加上這句path=path.replaceAll(” “, ” “);
API INSTANCE = (API)Native.loadLibrary(path, API.class);



對於jna來說,如果或直接在Eclipse裡執行的話,那麼
Native.loadLibrary(“hello”,**.class)
這兒第一個引數的當前目錄就是Eclipse的目錄。




相關文章