一。Java问题
1). package问题
网上的例子大部分都有package edu.netcom.jni;,编译时使用:javah package edu.netcom.jni
这是java package,不一定要照用,可使用简短的package,例如: Jni
2). C++ dll路径问题
C++编写的dll只需要放在java源码同一目录即可
3). 调用参数问题
Jni不能使用传出参数,只能通过返回值来传回结果,可传递数据,对象,对象数组(object[])
二。C++问题
1)。Jni包含路径问题
使用 $(JAVA_HOME)/include/win32 $(JAVA_HOME)/include
2)。字符串问题
java与C++使用的字符需要进行转换,特别是中文字符
3)。Java.String类型属性问题
例子:jfieldID fieldName = pJniEnv->GetFieldID(classServInfo, "strName", "Ljava/lang/String;");
4)。返回对象问题
函数返回单个对象,可使用Jni导出函数第二个参数jobject类型参数构造对象,也可定义新的返回对象,例
子:
jobject objRes = 0;
objRes = pJniEnv->AllocObject(classLoginResult);
5)。返回对象数组问题
函数返回对象数组,不能使用Jni导出函数第二个参数jobject类型参数构造对象,否则数组中的对象为同一
个对象,例子:
jobjectArray objArrayRes = 0;
//获取object所属类,一般为ava/lang/Object
jclass objClass = pJniEnv->FindClass("java/lang/Object");
// 获取java对象
jclass classServInfo = pJniEnv->FindClass("SOVJni/SOVGameServerInfo");
// 获取SOVGameServerInfo属性
jfieldID fieldId = pJniEnv->GetFieldID(classServInfo, "sId", "S");
jfieldID fieldName = pJniEnv->GetFieldID(classServInfo, "strName", "Ljava/lang/String;");
jfieldID fieldStatus = pJniEnv->GetFieldID(classServInfo, "cStatus", "B");
// 2008-09-10 得到类的构造函数
jmethodID mtdConstruct = pJniEnv->GetMethodID(classServInfo, "<init>", "()V");
// 构造对象数组
objArrayRes = pJniEnv->NewObjectArray(sServCount, objClass, 0);
// 构造多个对象
for (int s = 0; ; )
{
// 2008-09-10 java调用出现内存访问错误,原因是AllocObject
// jobject objServ = pJniEnv->AllocObject(classServInfo);
jobject objServ = pJniEnv->NewObject(classServInfo, mtdConstruct);
pJniEnv->SetShortField(objServ, fieldId, rServInfo.sId);
jstring strName = JStringConvert::WindowsToJString(pJniEnv, rServInfo.arName);
pJniEnv->SetObjectField(objServ, fieldName, strName);
pJniEnv->SetByteField(objServ, fieldStatus, rServInfo.cStatus);
pJniEnv->SetObjectArrayElement(objArrayRes, s, objServ);
}
三 。Java编译
可使用如下bat命令来编译Java程序,得到导出的C++接口
@if "%1" == "" goto error_1
@if "%1" == "/?" goto help
@if "%1" == "/help" goto help
@if "%2" == "" goto error_2
rem:进入目录
@cd %~p1
@cd %~d1
rem:编译%~n1%~x1文件
javac -d . %~n1%~x1
rem:生成C++接口文件%2.%~n1.h
javah %2.%~n1
@cd %~d1/
@goto end
:error_1
@echo "请输入要编译的java文件完整路径。"
goto end
:error_2
@echo "请输入Jni库的package名。"
goto end
:help
@echo JNICompare.bat 参数1 参数2 参数3
@echo 参数1 -- 要编译的java文件完整路径
@echo 参数2 -- java文件的package名
@echo 参数3 -- 其它命令,例如: exit
:end
%3
2008-09-10
四。AllocObject与NewObject
调用AllocObject产生jclass类定义对应的类实例对象;这不会调用任何类的构造函数,仅仅是内存创建。
调用NewObject产生jclass类定义对应的类实例对象;这需要提供类的构造方法的MethodID,会调用指定的
MethodID对应的构造函数。
五。java对象的构造函数
构造函数作为特例,方法名字为 <init>,返回类型为 ()V
C++获取 java对象构造函数的例子:
jmethodID mtdConstruct = pJni->GetMethodID(cls, "<init>", "()V");
六。函数返回类型
Java类型 对应的签名
boolean Z
byte B
char C
shrot S
int I
long L
float F
double D
void V
Object L用/分割包的完整类名; Ljava/lang/String;
Array [签名 [I [Ljava/lang/String;
七。javap命令
调用GetStaticMethodID获取jclass类定义指定类静态方法的MethodID;需要提供静态方法的名字和参数表
信息。这可以通过 jdk内置的命令 javap -s -c 类名字(不含class扩展名) 得到。
调用CallStatic<Type>Method执行指定MethodID对应的类的静态方法,其中<Type>应替换为函数返回值类
型的描述.如CallStaticIntMethod完成调用所有的返回值为Int的类的静态方法.
使用C++编写Jni库进行总结
最新推荐文章于 2024-03-27 14:53:34 发布