//==============================================================================// 功能:解析JavaClass文件生成Delphi开发Android单元//// 日期:2014年8月2日// 作者:ying32// QQ : 396506155// E-mail: yuanfen3287@vip.qq.com// MSN : ying_32@live.cn//// 注:一个简单的解析java class文件类, 没想要做得太复杂和// 灵活性, 因为转为Pascal的单元不需要其它一些信息,// 够用就行, 能读就行啊, 有兴趣的可以自行完善下//// 目前还有不少需要完善, 这个东西去年就想过要写, 但对// javaclass文件全然无知, 就一直没动手.// 手动转换单元太累了, 不过好久都没有碰过Android的开发了//// 前两天在网上看到了一个外国人写的一个这样的转换工具// 不过是收费的, 最便宜也要�90, 于是就重新开始研究//// JavaClass文件格式:// http://www.mobilefish.com/tutorials/java/java_quickguide_classfile.html//// 修改日志://// 2014年08月04日 更新和修正参数类型和返回值类型// 2014年08月28日 修正方法名与Delphi关键字冲突替换的字符,由 _ 改为 &//==============================================================================unit JavaClassFile;interfaceusesSystem.Classes,System.SysUtils;typeTReadConvert = classprotectedFStream: TStream;procedure ToBigEndian(Value: Pointer; nLen: Integer);publicconstructor Create(inStream: TStream); overload;function ReadByte: Byte;function ReadWord: Word;function ReadCardinal: Cardinal;function ReadUInt64: UInt64;function ReadShortInt: ShortInt;function ReadSmallInt: SmallInt;function ReadInteger: Integer;function ReadInt64: Int64;function ReadSingle: Single;function ReadDouble: Double;function ReadBytes(nLen: Word): TBytes; overload;procedure ReadBytes(out Buffer: TBytes; nLen: Word); overload;procedure Seek(APosi: Integer);end;TJavaClassFile = class(TObject)publictypePCp_Info = ^TCp_Info;TCp_Info = packed recordTag: Byte;Info: TArray<Byte>;end;PCONSTANT_Class_info = ^TCONSTANT_Class_info;TCONSTANT_Class_info = packed record//Tag: Byte;Name_Index: Word;end;PCONSTANT_Fieldref_info = ^TCONSTANT_Fieldref_info;TCONSTANT_Fieldref_info = packed record//Tag: Byte;Class_Index: Word;Name_And_Type_Index: Word;end;PCONSTANT_Methodref_info = ^TCONSTANT_Methodref_info;TCONSTANT_Methodref_info = packed record//Tag: Byte;Class_Index: Word;Name_And_Type_Index: Word;end;PCONSTANT_InterfaceMethodref_info = ^TCONSTANT_InterfaceMethodref_info;TCONSTANT_InterfaceMethodref_info = packed record//Tag: Byte;Class_Index: Word;Name_And_Type_Index: Word;end;PCONSTANT_String_info = ^TCONSTANT_String_info;TCONSTANT_String_info = packed record//Tag: Byte;String_Index: Word;end;PCONSTANT_Integer_info = ^TCONSTANT_Integer_info;TCONSTANT_Integer_info = packed record//Tag: Byte;Bytes: Cardinal;end;PCONSTANT_Long_info = ^TCONSTANT_Long_info;TCONSTANT_Long_info = packed record//Tag: Byte;High_Bytes: Cardinal;Low_Bytes: Cardinal;end;PCONSTANT_Double_info = ^TCONSTANT_Double_info;TCONSTANT_Double_info = packed record//Tag: Byte;High_Bytes: Cardinal;Low_Bytes: Cardinal;end;PCONSTANT_NameAndType_info = ^TCONSTANT_NameAndType_info;TCONSTANT_NameAndType_info = packed record//Tag: Byte;Name_Index: Word;Descriptor_Index: Word;end;PCONSTANT_Utf8_info = ^TCONSTANT_Utf8_info;TCONSTANT_Utf8_info = packed record//Tag: Byte;Length: Word;Bytes : TArray<Byte>;end;PCONSTANT_Float_info = ^TCONSTANT_Float_info;TCONSTANT_Float_info = packed record//Tag: Byte;Bytes: Cardinal;end;PCONSTANT_MethodHandle_info = ^TCONSTANT_MethodHandle_info;TCONSTANT_MethodHandle_info = packed record//Tag: Byte;Reference_Kind: Byte;ReferEnce_Index: Word;end;PCONSTANT_MethodType_info = ^TCONSTANT_MethodType_info;TCONSTANT_MethodType_info = packed record//Tag: Byte;Descriptor_Index: Word;end;PCONSTANT_InvokeDynamic_info = ^TCONSTANT_InvokeDynamic_info;TCONSTANT_InvokeDynamic_info = packed record//Tag: Byte;Bootstrap_Method_Attr_Index: Word;Name_And_Type_Index: Word;end;PAttribute_Info_Row1 = ^TAttribute_Info_Row1;TAttribute_Info_Row1 = packed recordStart_PC: Word;Line_Number: Word;end;PAttribute_Info_Row2 = ^TAttribute_Info_Row2;TAttribute_Info_Row2 = packed recordStart_PC: Word;Length: Word;Name_Index: Word;Descriptor_Index: Word;Index: Word;end;PAttribute_Info = ^TAttribute_Info;TAttribute_Info = packed recordAttribute_Name_Index: Word;Attribute_Length: Cardinal;Attribute_Row2: TArray<TAttribute_Info_Row2>;case Word of0 : (Constant_Value_Index: Word);1 : (Line_Number_Table_Length: Word);2 : (Local_Variable_Table_Length: Word);3 : (SourceFile_Index: Word);4 : (Number_Of_Classes: Word);end;PAttribute_Info2 = ^TAttribute_Info2;TAttribute_Info2 = packed recordAttribute_Name_Index: Word;Attribute_Length: Cardinal;Max_Stack: Word;Max_Locals: Word;Code_Length: Cardinal;Code: TArray<Byte>;Exception_Table_Length: Word;Attribute_Count: Word;Attr : TArray<TAttribute_Info>;end;PField_Info = ^TField_Info;TField_Info = packed recordAccess_Flags: Word;Name_Index: Word;Descriptor_Index: Word;Attributes_Count: Word;Attributes: TArray<TAttribute_Info>;end;PMethod_Info = ^TMethod_Info;TMethod_Info = packed recordAccess_Flags: Word;Name_Index: Word;Descriptor_Index: Word;Attributes_Count: Word;Attributes: TArray<TAttribute_Info2>;end;TClassFile = recordMagic: Cardinal;Minor: Word;Major: Word;ConstantPoolCount: Word;ConstantPool: TArray<TCp_Info>;AccessFlags: Word;ThisClass: Word;SuperClass: Word;InterfacesCount: Word;Interfaces: TArray<Word>;FieldsCount: Word;Fields: TArray<TField_Info>;MethodsCount: Word;Methods: TArray<TMethod_Info>;AttributesCount: Word;Attributes: TArray<TAttribute_Info>;end;public constMAGIC_CONST = $CAFEBABE;//ant types: ANTCONSTANT_Utf8 = 1;CONSTANT_Integer = 3;CONSTANT_Float = 4;CONSTANT_Long = 5;CONSTANT_Double = 6;CONSTANT_Class = 7;CONSTANT_String = 8;CONSTANT_Fieldref = 9;CONSTANT_Methodref = 10;CONSTANT_InterfaceMethodref = 11;CONSTANT_NameAndType = 12;CONSTANT_MethodHandle = 15;CONSTANT_MethodType = 16;CONSTANT_InvokeDynamic = 18;//Access Flags: ACCACC_PUBLIC = $0001;ACC_PRIVATE = $0002;ACC_PROTECTED = $0004;ACC_STATIC = $0008;ACC_FINAL = $0010;ACC_SYNCHRONIZED = $0020;ACC_SUPER = $0020; //Same as ACC_SYNCHRONIZEDACC_BRIDGE = $0040;ACC_VOLATILE = $0040; //Same as ACC_BRIDGEACC_VARARGS = $0080;ACC_TRANSIENT = $0080; //Same as ACC_VARARGSACC_NATIVE = $0100;ACC_INTERFACE = $0200;ACC_ABSTRACT = $0400;ACC_STRICT = $0800;ACC_SYNTHETIC = $1000;ACC_ANNOTATION = $2000;ACC_ENUM = $4000;privateFClassFile: TClassFile;procedure FreeMemory;procedure analyzerConstantPool(AData: TReadConvert; AIndex: Integer);procedure analyzerFieldPool(AData: TReadConvert; AIndex: Integer);procedure analyzerInterfacePool(AData: TReadConvert; AIndex: Integer);procedure analyzerMethodPool(AData: TReadConvert; AIndex: Integer);procedure analyzerAttributePool(AData: TReadConvert; AIndex: Integer);procedure CheckKeywords(var str: string);function getUTF8String(ACpInfo: TCP_Info): string;function getDataType(const S: string): string; overload;function getDataType(ACpInfo: TCP_Info): string; overload;function getParamsString(AMethod_Info: TMethod_Info): string;function getReturnDataType(const S: string): string;function ConvertToDelphiUnit: string;function GetClassName(AIndex: Integer): string;function GetThisClass: string;function GetSuperClass: string;publicconstructor Create;destructor Destroy; override;function Convert(AFileName: string): string;// property ThisClass: string read GetThisClass;public// property ClassFile: TClassFile read FClassFile;end;implementation{$IFDEF MSWINDOWS}usesWinapi.Windows;{$ENDIF}procedure println(Fmtstr: string; Args: array of const);begin{$IFDEF MSWINDOWS}OutputDebugString(PChar(Format(Fmtstr, Args)));{$ENDIF}end;{ TJavaClassFile }{TCONSTANT_Class_infoTCONSTANT_Fieldref_infoTCONSTANT_Methodref_infoTCONSTANT_InterfaceMethodref_infoTCONSTANT_String_infoTCONSTANT_Integer_infoTCONSTANT_Long_infoTCONSTANT_Double_infoTCONSTANT_NameAndType_infoTCONSTANT_Utf8_infoTCONSTANT_Float_infoTCONSTANT_MethodHandle_infoTCONSTANT_MethodType_infoTCONSTANT_InvokeDynamic_infoTAttribute_InfoTField_InfoTMethod_Info}procedure TJavaClassFile.analyzerAttributePool(AData: TReadConvert; AIndex: Integer);begin// 没写......有点用不着的样子end;procedure TJavaClassFile.analyzerConstantPool(AData: TReadConvert; AIndex: Integer);varLCpInfo: PCp_Info;LLen, LWord: Word;LU32: Cardinal;LFloat: Single;LUInt64: UInt64;LDouble: Double;LBytes: TBytes;beginLCpInfo := @FClassFile.ConstantPool[AIndex];LCpInfo^.Tag := AData.ReadByte;case LCpInfo^.Tag ofCONSTANT_Utf8 :beginLLen := AData.ReadWord;SetLength(LCpInfo^.Info, SizeOf(Word) + LLen);LBytes := AData.ReadBytes(LLen);Move(LBytes[0], LCpInfo^.Info[2], LLen);PCONSTANT_Utf8_info(LCpInfo^.Info)^.Length := LLen;end;CONSTANT_Integer :beginLU32 := AData.ReadCardinal;SetLength(LCpInfo^.Info, Sizeof(Cardinal));Move(LU32, LCpInfo^.Info[0], SizeOf(Cardinal));end;CONSTANT_Float :beginLFloat := AData.ReadSingle;SetLength(LCpInfo^.Info, Sizeof(Single));Move(LFloat, LCpInfo^.Info[0], SizeOf(Single));end;CONSTANT_Long :beginLUInt64 := AData.ReadUInt64;SetLength(LCpInfo^.Info, Sizeof(UInt64));Move(LUint64, LCpInfo^.Info[0], SizeOf(UInt64));end;CONSTANT_Double :beginLDouble := AData.ReadDouble;SetLength(LCpInfo^.Info, Sizeof(LDouble));Move(LDouble, LCpInfo^.Info[0], SizeOf(LDouble));end;CONSTANT_Class :beginLWord := AData.ReadWord;SetLength(LCpInfo^.Info, Sizeof(Word));PCONSTANT_Class_info(LCpInfo^.Info)^.Name_Index := LWord;//Move(LWord, LCpInfo^.Info[0], SizeOf(Word));end;CONSTANT_String :beginLWord := AData.ReadWord;SetLength(LCpInfo^.Info, Sizeof(Word));PCONSTANT_String_info(LCpInfo^.Info)^.String_Index := LWord;//Move(LWord, LCpInfo^.Info[0], SizeOf(Word));end;CONSTANT_Fieldref,CONSTANT_Methodref ,CONSTANT_InterfaceMethodref :beginSetLength(LCpInfo^.Info, Sizeof(Cardinal));LWord := AData.ReadWord;PCONSTANT_Fieldref_info(LCpInfo^.Info)^.Class_Index := LWord;LWord := AData.ReadWord;PCONSTANT_Fieldref_info(LCpInfo^.Info)^.Name_And_Type_Index := LWord;end;CONSTANT_NameAndType :beginSetLength(LCpInfo^.Info, Sizeof(Cardinal));LWord := AData.ReadWord;PCONSTANT_NameAndType_info(LCpInfo^.Info)^.Name_Index := LWord;LWord := AData.ReadWord;PCONSTANT_NameAndType_info(LCpInfo^.Info)^.Descriptor_Index := LWord;end;CONSTANT_MethodHandle :beginSetLength(LCpInfo^.Info, Sizeof(Cardinal));LWord := AData.ReadWord;PCONSTANT_MethodHandle_info(LCpInfo^.Info)^.Reference_Kind := LWord;LWord := AData.ReadWord;PCONSTANT_MethodHandle_info(LCpInfo^.Info)^.ReferEnce_Index := LWord;end;CONSTANT_MethodType :beginLWord := AData.ReadWord;SetLength(LCpInfo^.Info, Sizeof(Word));PCONSTANT_MethodType_info(LCpInfo^.Info)^.Descriptor_Index := LWord;end;CONSTANT_InvokeDynamic :beginSetLength(LCpInfo^.Info, Sizeof(Cardinal));LWord := AData.ReadWord;PCONSTANT_InvokeDynamic_info(LCpInfo^.Info)^.Bootstrap_Method_Attr_Index := LWord;LWord := AData.ReadWord;PCONSTANT_InvokeDynamic_info(LCpInfo^.Info)^.Name_And_Type_Index := LWord;end;end;end;{Access_Flags: Word;Name_Index: Word;Descriptor_Index: Word;Attributes_Count: Word;Attributes: TArray<TAttribute_Info>;}procedure TJavaClassFile.analyzerFieldPool(AData: TReadConvert; AIndex: Integer);varLField: PField_Info;I: Integer;beginLField := @FClassFile.Fields[AIndex];LField^.Access_Flags := AData.ReadWord;LField^.Name_Index := AData.ReadWord;LField^.Descriptor_Index := AData.ReadWord;LField^.Attributes_Count := AData.ReadWord;if LField^.Attributes_Count > 0 thenbeginSetLength(LField^.Attributes, LField^.Attributes_Count);for I := 0 to LField^.Attributes_Count - 1 dobeginLField^.Attributes[I].Attribute_Name_Index := AData.ReadWord;LField^.Attributes[I].Attribute_Length := AData.ReadCardinal;LField^.Attributes[I].Constant_Value_Index := AData.ReadWord;end;end;end;procedure TJavaClassFile.analyzerInterfacePool(AData: TReadConvert; AIndex: Integer);beginFClassFile.Interfaces[AIndex] := AData.ReadWord;end;procedure TJavaClassFile.analyzerMethodPool(AData: TReadConvert; AIndex: Integer);varLMethod: PMethod_Info;I, J, K: Integer;beginLMethod := @FClassFile.Methods[AIndex];LMethod^.Access_Flags := AData.ReadWord;LMethod^.Name_Index := AData.ReadWord;LMethod^.Descriptor_Index := AData.ReadWord;LMethod^.Attributes_Count := AData.ReadWord;//println('Index=%d', [AIndex]);if LMethod^.Attributes_Count > 0 thenbeginSetLength(LMethod^.Attributes, LMethod^.Attributes_Count);for I := 0 to LMethod^.Attributes_Count - 1 dobeginLMethod^.Attributes[I].Attribute_Name_Index := AData.ReadWord;LMethod^.Attributes[I].Attribute_Length := AData.ReadCardinal;//println('aaaaa=%d', [I]);// 跳过除代码段的if I >= 1 thenbeginAData.Seek(LMethod^.Attributes[I].Attribute_Length);Continue;end;LMethod^.Attributes[I].Max_Stack := AData.ReadWord;LMethod^.Attributes[I].Max_Locals := AData.ReadWord;LMethod^.Attributes[I].Code_Length := AData.ReadCardinal;AData.Seek(LMethod^.Attributes[I].Code_Length);LMethod^.Attributes[I].Exception_Table_Length := AData.ReadWord;LMethod^.Attributes[I].Attribute_Count := AData.ReadWord;if LMethod^.Attributes[I].Attribute_Count > 0 thenbeginSetLength(LMethod^.Attributes[I].Attr, LMethod^.Attributes[I].Attribute_Count);for J := 0 to LMethod^.Attributes[I].Attribute_Count - 1 dobegin//println('bbbbb=%d', [J]);LMethod^.Attributes[I].Attr[J].Attribute_Name_Index := AData.ReadWord;LMethod^.Attributes[I].Attr[J].Attribute_Length := AData.ReadCardinal;// println('AIndex=%d, 属性长度=%d,, I=%d, J=%d', [AIndex, LMethod^.Attributes[I].Attr[J].Attribute_Length, I, J]);if J = 0 thenbeginAData.Seek(LMethod^.Attributes[I].Attr[J].Attribute_Length);Continue;end;LMethod^.Attributes[I].Attr[J].Local_Variable_Table_Length := AData.ReadWord;if LMethod^.Attributes[I].Attr[J].Local_Variable_Table_Length > 0 thenbeginSetLength(LMethod^.Attributes[I].Attr[J].Attribute_Row2, LMethod^.Attributes[I].Attr[J].Local_Variable_Table_Length);for K := 0 to LMethod^.Attributes[I].Attr[J].Local_Variable_Table_Length - 1 dobegin//println('ddddd=%d', [K]);LMethod^.Attributes[I].Attr[J].Attribute_Row2[K].Start_PC := AData.ReadWord;LMethod^.Attributes[I].Attr[J].Attribute_Row2[K].Length := AData.ReadWord;LMethod^.Attributes[I].Attr[J].Attribute_Row2[K].Name_Index := AData.ReadWord;LMethod^.Attributes[I].Attr[J].Attribute_Row2[K].Descriptor_Index := AData.ReadWord;LMethod^.Attributes[I].Attr[J].Attribute_Row2[K].Index := AData.ReadWord;end;end;end;end;end;end;end;procedure TJavaClassFile.CheckKeywords(var str: string);constKeyWords_: array[0..1] of string = ('in', 'type');varI: Integer;beginfor I := 0 to High(KeyWords_) doif SameText(KeyWords_[I], Str.ToLower) thenStr := '&' + Str;end;function TJavaClassFile.Convert(AFileName: string): string;varLStream: TFileStream;LReadConvert: TReadConvert;I: Integer;beginResult := '';FillChar(FClassFile, SizeOf(TClassFile), 0);LStream := TFileStream.Create(AFileName, fmOpenRead);LReadConvert := TReadConvert.Create(LStream);tryFClassFile.Magic := LReadConvert.ReadCardinal;if FClassFile.Magic = TJavaClassFile.MAGIC_CONST thenbeginFClassFile.Minor := LReadConvert.ReadWord;FClassFile.Major := LReadConvert.ReadWord;// 分析常量池FClassFile.ConstantPoolCount := LReadConvert.ReadWord;if FClassFile.ConstantPoolCount > 0 thenbeginSetLength(FClassFile.ConstantPool, FClassFile.ConstantPoolCount);for I := 1 to FClassFile.ConstantPoolCount - 1 doanalyzerConstantPool(LReadConvert, I);end;FClassFile.AccessFlags := LReadConvert.ReadWord;FClassFile.ThisClass := LReadConvert.ReadWord;FClassFile.SuperClass := LReadConvert.ReadWord;// 分析接口FClassFile.InterfacesCount := LReadConvert.ReadWord;if FClassFile.InterfacesCount > 0 thenbeginSetLength(FClassFile.Interfaces, FClassFile.InterfacesCount);for I := 0 to FClassFile.InterfacesCount - 1 doanalyzerInterfacePool(LReadConvert, I);end;// 分析字段FClassFile.FieldsCount := LReadConvert.ReadWord;if FClassFile.FieldsCount > 0 thenbeginSetLength(FClassFile.Fields, FClassFile.FieldsCount);for I := 0 to FClassFile.FieldsCount - 1 doanalyzerFieldPool(LReadConvert, I);end;// 分析方法FClassFile.MethodsCount := LReadConvert.ReadWord;if FClassFile.MethodsCount > 0 thenbeginSetLength(FClassFile.Methods, FClassFile.MethodsCount);for I := 0 to FClassFile.MethodsCount - 1 doanalyzerMethodPool(LReadConvert, I);end;// 分析属性FClassFile.AttributesCount := LReadConvert.ReadWord;if FClassFile.AttributesCount > 0 thenbeginSetLength(FClassFile.Attributes, FClassFile.AttributesCount);for I := 0 to FClassFile.AttributesCount - 1 doanalyzerAttributePool(LReadConvert, I);end;Result := ConvertToDelphiUnit;end;finallyLStream.Free;LReadConvert.Free;Self.FreeMemory;end;end;constructor TJavaClassFile.Create;begininherited Create;end;destructor TJavaClassFile.Destroy;begininherited;end;procedure TJavaClassFile.FreeMemory;beginSetLength(FClassFile.ConstantPool, 0);SetLength(FClassFile.Interfaces, 0);SetLength(FClassFile.Fields, 0);SetLength(FClassFile.Methods, 0);SetLength(FClassFile.Attributes, 0);end;function TJavaClassFile.GetClassName(AIndex: Integer): string;varP: TCp_Info;beginResult := '';P := FClassFile.ConstantPool[AIndex];if P.Tag = CONSTANT_Class thenbeginP := FClassFile.ConstantPool[PCONSTANT_Class_info(P.Info).Name_Index];if P.Tag = CONSTANT_Utf8 thenResult := getUTF8String(P);end;end;function TJavaClassFile.getDataType(ACpInfo: TCP_Info): string;beginResult := getDataType(getUTF8String(ACpInfo))end;function TJavaClassFile.getDataType(const S: string): string;function getJavaClass(const S:string): string;beginResult := 'J' + S.Substring(S.LastDelimiter('/') + 1).Replace('$', '_').Replace(';', '');end;beginResult := S.Trim;case Result[1] of'B' : Result := 'Byte';'C' : Result := 'Char';'D' : Result := 'Double';'F' : Result := 'Single';'I' : Result := 'Integer';'J' : Result := 'Int64';'S' : Result := 'Word';'Z' : Result := 'Boolean';'V' : Result := '';'L' : Result := getJavaClass(Result);'[' :begincase Result[2] of'B' : Result := 'TArray<Byte>';'C' : Result := 'TArray<Char>';'D' : Result := 'TArray<Double>';'F' : Result := 'TArray<Single>';'I' : Result := 'TArray<Integer>';'J' : Result := 'TArray<Int64>';'L' : Result := Format('TArray<%s>', [getJavaClass(Result)]);'S' : Result := 'TArray<Word>';'Z' : Result := 'TArray<Boolean>';'V' : Result := '';end;end;end;end;function TJavaClassFile.getParamsString(AMethod_Info: TMethod_Info): string;varI: Integer;LParamName: string;LParamType: string;beginResult := '';if AMethod_Info.Attributes_Count > 0 thenif AMethod_Info.Attributes[0].Attribute_Count > 1 thenif AMethod_Info.Attributes[0].Attr[1].Local_Variable_Table_Length > 1 thenfor I := 1 to High(AMethod_Info.Attributes[0].Attr[1].Attribute_Row2) dobeginLParamName := getUTF8String(FClassFile.ConstantPool[AMethod_Info.Attributes[0].Attr[1].Attribute_Row2[I].Name_Index]);LParamType := getDataType(FClassFile.ConstantPool[AMethod_Info.Attributes[0].Attr[1].Attribute_Row2[I].Descriptor_Index]);CheckKeywords(LParamName);Result := Result + LParamName + ': ' + LParamType + '; ';end;Result := Result.Substring(0, Result.LastDelimiter(';') - 1);//Delete(Result, Length(Result) - 1, 2);end;function TJavaClassFile.getReturnDataType(const S: string): string;beginResult := getDataType(S.Substring(S.LastDelimiter(')')+1, S.Length - S.LastDelimiter(')')-1)).Trim;end;function TJavaClassFile.GetSuperClass: string;beginResult := GetClassName(FClassFile.SuperClass);end;function TJavaClassFile.GetThisClass: string;beginResult := GetClassName(FClassFile.ThisClass);end;function TJavaClassFile.getUTF8String(ACpInfo: TCP_Info): string;varLen: Word;LBytes: TBytes;beginResult := '';if ACpInfo.Tag <> CONSTANT_Utf8 then Exit;Len := PCONSTANT_Utf8_info(ACpInfo.Info)^.Length;SetLength(LBytes, Len);Move(ACpInfo.Info[2], LBytes[0], Len);Result := StringOf(LBytes);end;function TJavaClassFile.ConvertToDelphiUnit: string;varI: Integer;LFuncName, LDataType: string;StrList: TStringList;LJavaClass: string;LThisClass: string;LUnitName: string;procedure addstr(str: string);beginStrList.Add(str);end;function getJavaClass(str: string): string;beginResult := str.Substring(str.LastDelimiter('/') + 1, str.Length - str.LastDelimiter('/'));end;beginStrList := TStringList.Create;tryLThisClass := GetThisClass;LJavaClass := getJavaClass(LThisClass);LUnitName := 'Androidapi.JNI.' + LThisClass.Substring(LThisClass.IndexOf('/') + 1, LThisClass.Length - LThisClass.IndexOf('/')).Replace('/', '.');addstr('//====================================================');addstr('//');addstr('// 转换来自JavaClassToDelphiUnit');addstr('// 时间:' + DateTimeToStr(Now));addstr('// 作者:ying32');addstr('// QQ: 1444386932');addstr('// 396506155');addstr('// Email:yuanfen3287@vip.qq.com');addstr('// 个人小站:http://www.ying32.com');addstr('// 博客:http://blog.csdn.net/zyjying520');addstr('//');addstr('//====================================================');addstr(Format('unit %s;', [LUnitName]));addstr('');addstr('interface');addstr('');addstr('uses'); // 引用文件,还没弄addstr(' Androidapi.JNIBridge,');addstr(' Androidapi.JNI.JavaTypes;');addstr('');addstr('');addstr('type');addstr(Format(' J%s = interface; // %s', [LJavaClass, LThisClass.Replace('/', '.')]));addstr('');addstr(Format(' J%sClass = interface(J%sClass)', [LJavaClass, getJavaClass(GetSuperClass)])); // 这里还有接口了, 枚举了????addstr(Format(' [''%s'']', [TGUID.NewGuid.ToString]));addstr(' { Property Methods }');for I := 0 to FClassFile.FieldsCount - 1 dobeginLFuncName := getUTF8String(FClassFile.ConstantPool[FClassFile.Fields[I].Name_Index]);LDataType := getDataType(FClassFile.ConstantPool[FClassFile.Fields[I].Descriptor_Index]);addstr(Format(' function _GET%s: %s;', [LFuncName, LDataType]));end;addstr('');addstr(' { static Methods }');for I := 0 to FClassFile.MethodsCount - 1 dobeginLFuncName := getUTF8String(FClassFile.ConstantPool[FClassFile.Methods[I].Name_Index]);LDataType := getDataType(FClassFile.ConstantPool[FClassFile.Methods[I].Descriptor_Index]);if SameText(LFuncName, '<init>') thenaddstr(Format(' function init(%s): J%s; cdecl;', [getParamsString(FClassFile.Methods[I]), LJavaClass])); // 方法的重载标识没添加// public staticif FClassFile.Methods[I].Access_Flags = 9 thenaddstr(Format(' function %s(%s): J%s; cdecl;', [LFuncName, getParamsString(FClassFile.Methods[I]), LJavaClass]));end;addstr('');addstr(' { Property }');for I := 0 to FClassFile.FieldsCount - 1 dobeginLFuncName := getUTF8String(FClassFile.ConstantPool[FClassFile.Fields[I].Name_Index]);LDataType := getDataType(FClassFile.ConstantPool[FClassFile.Fields[I].Descriptor_Index]);addstr(Format(' property %s: %s read _GET%s;', [LFuncName, LDataType, LFuncName]));end;addstr(' end;');addstr('');addstr(Format(' [JavaSignature(''%s'')]', [LThisClass]));addstr(Format(' J%s = interface(J%s)', [LJavaClass, getJavaClass(GetSuperClass)]));addstr(Format(' [''%s'']', [TGUID.NewGuid.ToString]));addstr(' { methods }');for I := 0 to FClassFile.MethodsCount - 1 dobeginLFuncName := getUTF8String(FClassFile.ConstantPool[FClassFile.Methods[I].Name_Index]);// public 其它还有,自行搞定if (FClassFile.Methods[I].Access_Flags = ACC_PUBLIC) and (not SameText('<init>', LFuncName)) thenbeginLDataType := getDataType(FClassFile.ConstantPool[FClassFile.Methods[I].Descriptor_Index]);if getReturnDataType(LDataType).Length = 0 thenaddstr(Format(' procedure %s(%s); cdecl;', [LFuncName, getParamsString(FClassFile.Methods[I])]))elseaddstr(Format(' function %s(%s): %s; cdecl;', [LFuncName, getParamsString(FClassFile.Methods[I]), getReturnDataType(LDataType)]));end;end;addstr(' end;');addstr('');addstr(Format(' TJ%s = class(TJavaGenericImport<J%sClass, J%s>) end;', [LJavaClass, LJavaClass, LJavaClass]));addstr('');addstr('implementation');addstr('');addstr('end.');Result := StrList.Text;StrList.SaveToFile(ExtractFilePath(ParamStr(0)) + LUnitName + '.pas');finallyStrList.Free;end;end;{ TReadConvert }constructor TReadConvert.Create(inStream: TStream);beginFStream := inStream;FStream.Position := 0;end;function TReadConvert.ReadByte: Byte;beginFStream.Read(Result, 1);end;procedure TReadConvert.ReadBytes(out Buffer: TBytes; nLen: Word);beginif Buffer <> nil then FStream.Read(Buffer, nLen);end;function TReadConvert.ReadBytes(nLen: Word): TBytes;beginSetLength(Result, nLen);FStream.Read(Result[0], nLen);end;function TReadConvert.ReadCardinal: Cardinal;beginFStream.Read(Result, 4);ToBigEndian(@Result, 4);end;function TReadConvert.ReadDouble: Double;beginFStream.Read(Result, 8);ToBigEndian(@Result, 8);end;function TReadConvert.ReadInt64: Int64;beginFStream.Read(Result, 8);ToBigEndian(@Result, 8);end;function TReadConvert.ReadInteger: Integer;beginFStream.Read(Result, 4);ToBigEndian(@Result, 4);end;function TReadConvert.ReadShortInt: ShortInt;beginFStream.Read(Result, 1);end;function TReadConvert.ReadSingle: Single;beginFStream.Read(Result, 4);ToBigEndian(@Result, 4);end;function TReadConvert.ReadSmallInt: SmallInt;beginFStream.Read(Result, 2);ToBigEndian(@Result, 2);end;function TReadConvert.ReadUInt64: UInt64;beginFStream.Read(Result, 8);ToBigEndian(@Result, 8);end;function TReadConvert.ReadWord: Word;beginFStream.Read(Result, 2);ToBigEndian(@Result, 2);end;procedure TReadConvert.Seek(APosi: Integer);beginFStream.Position := FStream.Position + APosi;end;procedure TReadConvert.ToBigEndian(Value: Pointer; nLen: Integer);varLWord: Word;LCardinal: Cardinal;LUInt64: UInt64;begincase nLen of2 :beginLWord := (Word(PByte(Value)^) shl 8) + Word(PByte(Cardinal(Value) + 1)^);PWord(Value)^ := LWord;end;4 :beginLCardinal :=(Cardinal(PByte(Value)^) shl 24) +(Cardinal(PByte(Cardinal(Value) + 1)^) shl 16) +(Cardinal(PByte(Cardinal(Value) + 2)^) shl 8) +Cardinal(PByte(Cardinal(Value) + 3)^);PCardinal(Value)^ := LCardinal;end;8 :beginLUInt64 :=(UInt64(PByte(Cardinal(Value) + 1)^) shl 56) +(UInt64(PByte(Value)^) shl 48) +(UInt64(PByte(Cardinal(Value) + 1)^) shl 40) +(UInt64(PByte(Cardinal(Value) + 2)^) shl 32) +(UInt64(PByte(Value)^) shl 24) +(UInt64(PByte(Cardinal(Value) + 1)^) shl 16) +(UInt64(PByte(Cardinal(Value) + 2)^) shl 8) +UInt64(PByte(Cardinal(Value) + 3)^);PUInt64(Value)^ := LUInt64;end;end;end;end.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。