錯誤:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Test.testPrint(Ljava/lang/String;)V
at Test.testPrint(Native Method)
at Test.main(Test.java:8)
解決方法:
昨天一天都在想辦法解決這個問題,操作步驟按照教程來的,怎么會出錯呢?
想了半天,覺得還是dll文件生成的不對。所以,最后決定把codeblocks換成visual c++來編譯生成dll文件,最后一試成功了。
------------------------------我是分割線----------------------------------------------------------------------------------------------------------------
Java中如何調用c/c++
1、首先打開eclipse,新建一個eclipse工程,編寫一個java類。
如下所示:
public class Test {
public native void testPrint(String str);//1
public static void main(String[] args){
System.loadLibrary("TestAgain");//2
Test test = new Test();
test.testPrint("this is a test");
}
}
分析這個程序,1處使用native關鍵字申明了一個本地方法,這個方法我們在后面要用c/c++實現
2處則是在java中通過libname:TestAgain加載本地方法庫。
這里可以使用System.loadLibrary("xxx");//xxx是生成的dll文件的名字加載本地方法庫,也可以通過System.load("E:/eclipseWork/Test/TestAgain.dll")來加載本地方法庫,load方法里面需要填寫絕對路徑。
2、然后使用 javac -d . Test.java 生成類文件
3、再使用 javah -jni Test 生成.h文件
生成的.h文件如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Test */
#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Test
* Method: testPrint
* Signature: (Ljava/lang/String;)V//1
*/
JNIEXPORT void JNICALL Java_Test_testPrint
(JNIEnv *, jobject, jstring); //2
#ifdef __cplusplus
}
#endif
#endif
這個和我們平常的.h文件沒有什么差別,都是用來申明函數的,不過它是機器自動生成的,所以不要修改。
1處,是一個標記符,當從本地方法端訪問java端的時候就會用到。
java類型 | Signature | 備注 |
boolean | Z | |
byte | B | |
char | C | |
short | S | |
int | I | |
long | L | |
float | F | |
double | D | |
void | V | |
object | L用/分割的完整類名 | 例如: Ljava/lang/String表示String類型 |
Array | [簽名 | 例如: [I表示int數組, [Ljava/lang/String表示String數組 |
Method | (參數簽名)返回類型簽名 | 例如: ([I)I表示參數類型為int數組, 返回int類型的方法 |
(表格摘自http://www.cnblogs.com/icejoywoo/archive/2012/02/22/2363709.html)
2處是函數申明,我們在c/c++中需要實現
4、用visual c++新建一個dll工程。test.h文件中包含#include <jni.h>,包含的jni.h存在於JDK安裝目錄下的include下面。需要將他們添加進來。
Tools->Options->Directories,新建Directions。
再就是用c/c++實現本地方法,注意.c/.cpp中的函數名必須和.h中的函數名一致
下面是.cpp的代碼
#include "windows.h"
#include "Test.h"
#include "iostream.h"
/*
* Class: Test
* Method: testPrint
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Test_testPrint(JNIEnv * env, jobject obj, jstring str){
const char *msg;
msg = env->GetStringUTFChars(str,0);
cout<<"the msg is"<<endl;
cout<<msg<<endl;
env->ReleaseStringUTFChars(str,msg);
}
5、編譯通過生成TestAgain.dll。將它復制到之前建的eclipse工程根目錄下面
6、回到eclipse界面,F5刷新工程,然后run。結果如下
這樣就實現了在Java中調用c/c++。