Test.java
__________________________________
public class Test
{
public static native void p();
public static void main(String[] args)
{
System.loadLibrary("TestDll");
p();
}
}
javac Test.java
javah -jni Test //命令生成的test.c头文件
/* 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: p
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Test_p
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
testdll.c (将 c:jdkin下面的 jni.h 和 jni_md.h 复制到当前c程序的文件夹里)
________________________________
#include "jni.h"
#include "test.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_Test_p(JNIEnv *env, jobject obj)
{
printf("Hello world!
");
return;
}
用code::Blocks生成的dll,使用DLL Export Viewer查看其函数名是Java_Test_p@8。
cmd> java Test 抛出错误:
java.lang.UnsatisfiedLinkError: Test.p()V
___________________________________________
解决的第1种方法:
在testdll.h文件中把"Java_Hello_p"函数前的"JNICALL"去掉,重编dll就能测试通过。(注: #define JNICALL __stdcall),网上的查到的资料如下:
HTML code
stdcall的调用约定意味着:1)参数从右向左压入堆栈,2)函数自身修改堆栈 3)函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。
___________________________________________
解决的第2种方法:@silenceburn (http://topic.csdn.net/u/20110216/15/d85cf526-beb9-4a36-b6c2-7ade7f1eb01d.html)
正好手边有codeBlocks,就测试了一下,的确会有LZ说的问题,
放狗搜了搜,是因为JNI想要VC风格的函数声明,但是CodeBlocks默认的GCC编译器生成的是GCC风格的
需要用编译选项修改生成风格,8L的兄弟说的是对的。
修改的位置在CodeBlocks的工程右键properties - Build Targets - Build Options - Linker Setting - Other Linker Options ,加入 -Wl,--kill-at 即可。我在我本机已经测试通过。
___________________________________________
在测试通过java传字符串到c写的dll时,发现在c程序中打印出来的中文会出现乱码情况,在百度搜索后找到一个解决方法:
#include "jni.h"
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
char* jstringToWindows( JNIEnv *env, jstring jstr );
jstring WindowsTojstring( JNIEnv* env, char* str );
JNIEXPORT void JNICALL Java_Test_p(JNIEnv *env, jobject obj)
{
printf("Hello world!
");
return;
}
//通过java传字符串过来
JNIEXPORT void JNICALL Java_Test_abcd(JNIEnv *env, jobject obj, jstring p)
{
const char * str = jstringToWindows( env, p );
printf( "%s
" , str);
/*
如果把上句改为下句,C接收Java字符串时将出现乱码:
//const char* str = (*env)->GetStringUTFChars(env, p, 0);
//printf("%s",str);
*/
}
//需要用一下2个函数做编码格式转换
char* jstringToWindows( JNIEnv *env, jstring jstr )
{
int length = (*env)->GetStringLength(env,jstr );
const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 );
char* rtn = (char*)malloc( length*2+1 );
int size = 0;
size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
if( size <= 0 )
return NULL;
(*env)->ReleaseStringChars(env,jstr, jcstr );
rtn[size] = 0;
return rtn;
}
jstring WindowsTojstring( JNIEnv* env, char* str )
{
jstring rtn = 0;
int slen = strlen(str);
unsigned short* buffer = 0;
if( slen == 0 )
rtn = (*env)->NewStringUTF(env,str );
else
{
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
buffer = malloc( length*2 + 1 );
if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
rtn = (*env)->NewString( env, (jchar*)buffer, length );
}
if( buffer )
free( buffer );
return rtn;
}