vložil Karel
30. července 2012 21:45
Před časem jsem psal o propojení projektů v Javě a Delphi prostřednictvím rozhraní JNI (unit JNI.pas). S přechodem na Windows 7 64bit a Java 1.7 64bit vyvstal jeden nepříjemný problém. Tím je generování výjimky Access violation v unitu JNI.pas v metodě TJNIEnv.ArgsToJValues, která má za úkol převést pole pascalských argumentů na pole argumentů pro Javu.
V originále zmíněná metoda vypadá takto:
function TJNIEnv.ArgsToJValues(const Args: array of const): PJValue;
var
I: Integer;
begin
if Length(Args) <> Length(FConvertedArgs) then
SetLength(FConvertedArgs, Length(Args));
for I := 0 to High(Args) do
case Args[I].VType of
vtInteger:
FConvertedArgs[I].i := JInt(Args[I].VInteger);
vtBoolean:
FConvertedArgs[I].z := JBoolean(Args[I].VBoolean);
vtWideChar:
FConvertedArgs[I].c := JChar(Args[I].VWideChar);
vtInt64:
FConvertedArgs[I].j := JLong(Args[I].VInt64^);
vtPointer, vtObject:
FConvertedArgs[I].l := JObject(Args[I].VObject);
vtAnsiString:
FConvertedArgs[I].l := StringToJString(UTF8String(PAnsiString(Args[I].VAnsiString)^));
vtWideString:
FConvertedArgs[I].l := WideStringToJString(PWideString(Args[I].VWideString)^);
{$IFDEF HAS_UNICODESTRING}
vtUnicodeString:
FConvertedArgs[I].l := WideStringToJString(PUnicodeString(Args[I].VUnicodeString)^);
{$ENDIF}
vtExtended:
FConvertedArgs[I].d := Args[I].VExtended^; // Extended to Double (we lose Floats here)
else
raise EJNIError.Create('Unsupported variant argument');
end;
Result := PJValue(FConvertedArgs);
end;
Kompilátor si ovšem správně neporadí s použitými konstrukcemi pro převod řetězců na argumenty typu JValue, což má za následek nepříjemný pád, ke kterému dojde, když program zabrousí na některou z níže uvedených řádek kódu:
FConvertedArgs[I].l := StringToJString(UTF8String(PAnsiString(Args[I].VAnsiString)^));
FConvertedArgs[I].l := WideStringToJString(PWideString(Args[I].VWideString)^);
FConvertedArgs[I].l := WideStringToJString(PUnicodeString(Args[I].VUnicodeString)^);
Nepátral jsem sice po přesných příčinách těchto havárií, ale zdá se, že způsobené pády dostatečně řeší následující úprava kódu:
FConvertedArgs[I].l := StringToJString(UTF8String(PAnsiString(Args[I].VAnsiString)));
FConvertedArgs[I].l := WideStringToJString(PChar(PWideString(Args[I].VWideString)));
FConvertedArgs[I].l := WideStringToJString(PChar(PUnicodeString(Args[I].VUnicodeString)));