Delphi.cz

Český portál Delphi

Ještě jednou Delphi a Java, tentokrát v XE2 64bit

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)));

Datum: 2012-07-30 20:45:00 Tagy: fix, java, DelphiXE2

Praxe