function Java_com_erm_controller_ARMReports_S35(PEnv: PJNIEnv; Obj: JObject; ex_UserRowID, ex_BSID : Integer; ex_RevalDate : JString;
ex_AFS, ex_HTM, ex_HFT : Boolean;
ex_IsMcCaulay_PNL: Boolean;
ex_Maturity, ex_Scale : JIntArray
): Integer; stdcall; export;
var objRpt : TARMReports;
I : Integer;
Len : JInt; //just a renamed delphi integer
aMaturity:array of Integer;
aScale:array of Integer;
begin
DLLErrorLog('CASH -S35');
objRpt := TARMReports.Create; JVM := TJNIEnv.Create(PEnv); ex_RevalDate_J := JVM.JStringToString(ex_RevalDate);
Len:=PEnv^.GetArrayLength(PEnv, ex_Maturity);
SetLength(aMaturity, Len);
Len:=PEnv^.GetArrayLength(PEnv, ex_Scale);
SetLength(aScale, Len);
DLLErrorLog('ex_Maturity Length'+ intToStr(Len));
for I := 0 to Len-1 do
begin
PEnv^.GetIntArrayRegion(PEnv, ex_Maturity, I, Len, @aMaturity[I]);
DLLErrorLog('ex_Maturity '+ IntToStr(aMaturity[I]));
PEnv^.GetIntArrayRegion(PEnv, ex_Scale, I, Len, @aScale[I]);
DLLErrorLog('ex_Scale '+ IntToStr(aScale[I]));
end;
Result := objRpt.S35(ex_UserRowID, ex_BSID, ex_RevalDate_J,
ex_AFS, ex_HTM, ex_HFT ,
ex_IsMcCaulay_PNL,
aMaturity, aScale
);
DLLErrorLog('CASH2 Ends -S35');
JVM.Free; objRpt.Free;
end;
需要将ex_Maturity
,ex_Scale
转换为Delphi的Array of Integer
对象。
现在从Java调用它会抛出 java.lang.ArrayIndexOutOfBoundsException
在Log数组值中打印时正在进行。请建议我们为我工作。
答案 0 :(得分:2)
有几种方法,具体取决于您的JIntArray 。
首先,如果它是 int 的数组(如原始java类型),则通过JNI获取数组的长度,分配一个整数的delphi数组,然后让JNI复制来自java数组的数据
Uses
AndroidAPI.JNI;
Var
Len:JNIInt; //just a renamed delphi integer
aMaturity:array of integer;
begin
Len:=PEnv^.GetArrayLength(PEnv, ex_Maturity);
//allocate the receiving array
SetLength(aMaturity, Len);
//now get the array data - note we are passing the address of the first element
//not the address of the array itself!
PEnv^.GetIntArrayRegion(PEnv, ex_Maturity, 0, Len, @aMaturity[0]);
//do stuff
end;
如果您正在处理一个Integer数组(即Java类“Integer”),那么您需要一次从JNI获取一个对象数组,并使用TJNIResolver获取原始值;
Uses
AndroidAPI.JNI, AndroidAPI.JNIBridge;
Var
Len:JNIInt; //just a renamed delphi integer
Count:Integer;
Current:JNIObject;
CurrentValue:integer;
aMaturity:array of integer;
begin
Len:=PEnv^.GetArrayLength(PEnv, ex_Maturity);
//allocate the receiving array
SetLength(aMaturity, Len);
For Count:=0 to Len-1 do
begin
Current:=PEnv^.GetObjectArrayElement(PEnv, ex_Maturity, Count);
if assigned(Current) then
begin
CurrentValue:=TJNIResolver.GetRawValueFromJInteger(Current);
//Yes, you can inline this but the point is, here you do stuff with
//the element
aMaturity[Count]:=CurrentValue;
end;
end;
end;
显然第一种方法要快得多,因为越过JNI障碍慢并且你只做了一次,而对于Java Integers数组你每次做多次元件
您还应该注意错误 - 如果您不处理它们,我不会在任何可能崩溃和烧毁您应用的点检查Java异常。
编辑:OP已准备好我的答案并尝试使用它,这很好。他们的代码中有一个超出范围的例外。
function Java_com_erm_controller_ARMReports_S35(PEnv: PJNIEnv; Obj: JObject; ex_UserRowID, ex_BSID : Integer; ex_RevalDate : JString;
ex_AFS, ex_HTM, ex_HFT : Boolean;
ex_IsMcCaulay_PNL: Boolean;
ex_Maturity, ex_Scale : JIntArray
): Integer; stdcall; export;
var objRpt : TARMReports;
I : Integer;
Len : JInt; //just a renamed delphi integer
aMaturity:array of Integer;
aScale:array of Integer;
begin
DLLErrorLog('CASH -S35');
objRpt := TARMReports.Create; JVM := TJNIEnv.Create(PEnv); ex_RevalDate_J := JVM.JStringToString(ex_RevalDate);
//you only have 1 length defined and possibly different array lengths
//process arrays seperately
Len:=PEnv^.GetArrayLength(PEnv, ex_Maturity);
SetLength(aMaturity, Len);
DLLErrorLog('ex_Maturity Length'+ intToStr(Len));
//only call this once, also watch the parameters you are passing in
PEnv^.GetIntArrayRegion(PEnv, ex_Maturity, 0, Len, @aMaturity[0]);
Len:=PEnv^.GetArrayLength(PEnv, ex_Scale);
SetLength(aScale, Len);
DLLErrorLog('ex_Scale Length'+ intToStr(Len));
PEnv^.GetIntArrayRegion(PEnv, ex_Scale, 0, Len, @aScale[0]);
Result := objRpt.S35(ex_UserRowID, ex_BSID, ex_RevalDate_J,
ex_AFS, ex_HTM, ex_HFT ,
ex_IsMcCaulay_PNL,
aMaturity, aScale
);
DLLErrorLog('CASH2 Ends -S35');
JVM.Free; objRpt.Free;
end;
你正在做的是获得两次长度,正确设置delphi数组,然后在同一个循环中循环它们,而不考虑它们可能是不同的长度。你对 getinarrayregion 的调用也为两个调用的第二个参数传递了aScale的完整长度 - 如果你真的想让每个调用都像那样循环那么你需要传递计数和一个长度为1只返回1个元素 - 这很可能是造成异常的原因。
如果你想报告内容,然后创建一个程序来做,而不是在你当前的程序中使用循环,你将不得不复制和粘贴循环来做它否则这是,不明确的坏编码实践和我们我现在不想要吗?
讽刺 并不是期望有人试图帮助你纠正你的代码,而不是真正理解问题是更好的,但哼哼。 讽刺