求教高手:有关DLL调用中参数传递问题???
使用JNI调用DLL中的函数,DLL中函数原形:
SendMsg(long CommIndex,char * Msg,bool Chinese);
在JAVA类中写成如下声明:
public native long MySendMsg(long CommIndex,String Msg,boolean Chinese);
JAVA中调用如下:
System.out.println(mysm.MySendMsg(1,"参数传递测试abcd",true));
结果经测试long与boolean类型的参数可以正确传递到DLL函数,而String类型参数传递不成功,请问char *在JAVA中如何定义,在JAVA中调用带String类型参数的函数应该如何附值呀?
谢谢!
问题点数:50、回复次数:12Top
1 楼Jacky1206(胖胖,其实我不胖)回复于 2002-09-27 14:11:59 得分 10
java本地接口定义了如下的一些类型jboolean,jbyte,jchar,jshort,jint,jlong,jfloat,jdouble,jstring,所以你的c中声明的char在使用JNI时要用jchar类型才可以,至于赋值给个简单的例子:
JNIEXPORT jstring JNICALL Java_HelloNative_getGreeting
(JNIEnv * env,jclass cl)
{
jstring jstr;
jstr=NewStringUTF("Hello,Native World\n");
return jstr;
}
谢谢!
Top
2 楼xiaosongyu(松)回复于 2002-09-27 14:27:36 得分 0
to ITBUG (IT浪子) :
>结果经测试long与boolean类型的参数可以正确传递到DLL函数
你测试成功了??如果DLL中函数原型是
SendMsg(long CommIndex,char * Msg,bool Chinese);
的话,我不太相信。
Top
3 楼ITBUG(IT浪子)回复于 2002-09-27 15:04:43 得分 0
to Jacky1206():
我的意思是:在JAVA中调用
MySendMsg(long CommIndex,String Msg,boolean Chinese);
其中String Msg是调用时动态指定的,而不是写死的,难到JAVA中没有动态参数
设置?你讲的jchar类型,在JAVA中如何定义才能用javac.exe 与javah.exe
倒出*.h中的函数原形,请再指教一下。
to xiaosongyu(松) :
long和boolean是可以传递的,就是String 好象不行。
Top
4 楼xiaosongyu(松)回复于 2002-09-27 15:35:23 得分 0
String不是不行,是方法不对,下面是JNI的一些代码
http://www.hugkc.org/sigs/c/files/jniexamples.zip
可以参考一下,另外好好看一下JNI的文档Top
5 楼ITBUG(IT浪子)回复于 2002-09-27 17:17:01 得分 0
实际就是如何正确的把jstring类型转化为char* ?Top
6 楼xzyhero(大志)回复于 2002-09-27 20:23:28 得分 0
学习Top
7 楼xiaosongyu(松)回复于 2002-09-28 13:04:37 得分 0
具体的说就是jniexamples.zip中chap8例子中NativeString.c里面的
char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
方法,它的作用就是将jstring类型转化为char*,其实知道了很简单,就是先在C语言中调用java的String类型的getBytes方法,将java字符串对象转化为java的byte数组,然后再调用JNI函数GetByteArrayRegion将这个byte数组转化为C语言的char数组。
在刚学习JNI的时候,因为JNI的文档不够详细,如果没有人指导的话,在这个地方理解失误在所难免,我当时也是走了好多弯路才弄明白怎么回事的,jniexamples.zip里面的例子不错,好像是某一本书的实例代码,我认为是JNI入门的好东东,我极力向大家推荐!!
Top
8 楼xiaosongyu(松)回复于 2002-09-28 13:06:26 得分 0
我在学习JNI的时候写了一些代码,很简单,那天找到了贴上来,大家共享Top
9 楼ITBUG(IT浪子)回复于 2002-09-28 14:42:29 得分 0
非常感谢谢谢 xiaosongyu(松):
以下是我实现的代码,经验证可用,但中文string好象不行
JNIEXPORT jlong JNICALL Java_sm_MySendMsg
(JNIEnv *env, jobject, jlong jl1, jstring js1,jstring js2, jlong jl2, jboolean jb1)
{
const char *str1 =env->GetStringUTFChars(js1,0);
const char *str2 =env->GetStringUTFChars(js2,0);
char s1[50];
char s2[50];
strcpy(s1,str1);
strcpy(s2,str2);
env->ReleaseStringUTFChars(js1,str1);
env->ReleaseStringUTFChars(js2,str2);
}Top
10 楼xiaosongyu(松)回复于 2002-09-28 16:21:13 得分 40
下面是我以前写的部分代码,中文绝对没有任何问题,分别是从String到char*和从char*到String的转化,可以参考一下
//函数ChgStringNativeChars,用以将java的String类型转化为C++的字符串
//要转化的Java的String放在jstr中,返回结果在str中
//返回值:
// 0 错误
// 1 成功
int ChgStringNativeChars( JNIEnv *env, jobject jstr, char *str, int strlen ) {
jclass JClsString; //java的String类的类指针
jmethodID JMthdStringGetbytes; //java的String类的getbytes方法ID
jbyteArray bytes = NULL;
jthrowable excute; //定义异常,判断是否发生java异常使用
JClsString = env->FindClass( "java/lang/String" );
if( JClsString == NULL )
return 0;
JMthdStringGetbytes = env->GetMethodID( JClsString, "getBytes", "()[B" );
if( JMthdStringGetbytes == NULL )
return 0;
if( env->EnsureLocalCapacity( 2 ) < 0 )
return 0; //内存不足
bytes = (jbyteArray) env->CallObjectMethod( jstr, JMthdStringGetbytes ); //先将java的String转化为java的byte数组
excute = env->ExceptionOccurred(); //是否发生异常
if(!excute) { //未发生异常
jint len = env->GetArrayLength( bytes );
if( len >= strlen ) { //字符串超长
env->DeleteLocalRef( bytes );
return 0;
}
env->GetByteArrayRegion( bytes, 0, len, (jbyte *)str );
str[len]=NULL;
}
else { //发生异常
env->DeleteLocalRef( excute );
}
env->DeleteLocalRef( bytes );
return 1;
}
//函数NativeChgCharsString,用以将C++的字符串转化为java的String类型
//要转化的字符串放在str中
//返回值:
// NULL 错误
// jstring对象 成功
jstring ChgNativeCharsString( JNIEnv *env, char *str ) {
jstring jstr;
jclass JClsString; //java的String类的类指针
jmethodID JMthdStringInit; //java的String类的初始化方法的方法ID
jshort len;
jbyteArray bytes = NULL;
JClsString = env->FindClass( "java/lang/String" );
if( JClsString == NULL )
return NULL;
JMthdStringInit = env->GetMethodID( JClsString, "<init>", "([B)V" );
if( JMthdStringInit == NULL )
return NULL;
if( env->EnsureLocalCapacity( 2 ) < 0 )
return NULL; //内存不足
len = strlen( str );
bytes = env->NewByteArray( len );
if( bytes != NULL ) {
env->SetByteArrayRegion( bytes, 0, len, (jbyte *)str );
jstr = (jstring) env->NewObject( JClsString, JMthdStringInit, bytes );
env->DeleteLocalRef( bytes );
return jstr; //正常退出
}
return NULL; //非正常退出
}
Top
11 楼xiaosongyu(松)回复于 2002-09-28 16:26:17 得分 0
需要说明的是:
由于一些原因,我在实现ChgStringNativeChars时采用了另外的一种办法,即把String作为一个普通的Object来操作,仔细看一下,应该也可以弄明白的。
我的代码也可能会有一些问题,欢迎大家一起帮我分析一下。Top
12 楼ITBUG(IT浪子)回复于 2002-09-29 17:08:35 得分 0
现在使用JNI调用第三方开发的DLL已经没有问题了。Top




