在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在Windows中开发DLL时,经常会需要获取当前DLL所在目录以便读取同目录下的其他文件,而目前Delphi在开发android时,其实没多大必要获取,因为整个工程只有一个so文件,而这个so文件也可以通过引用System.IOUtils,再使用TPath.GetLibraryPath()即可。 不过有时候我们确实需要用到类似Windows中GetModuleFileName和GetModuleHandle等函数, 这些我们应该如何在android中去实现呢? 1.linux中的进程管理/proc/[PID]/XXXX在linux中乃至各种遵循posix的unix类系统,均可以在/proc/路径下面得到系统各种进程的相关信息,因此下面的代码在MacOS和iOS中其实是可以通用的,因为Posix标准就是为了可移植而定义的,对于开发人员来说,用一套代码走遍所有系统是非常高兴的事,而进程各个模块的信息则在maps文件中。 2.实现android版的GetModuleFileName下面各种版本的实现代码: 2.1 FreePascal 代码1 //可支持android和linux 2 uses 3 {$IFDEF FPC} 4 {$IFDEF UNIX} 5 //BaseUnix, Unix, 6 dl; 7 {$ENDIF} 8 {$ENDIF}
2.2 delphi XE7 代码1 //支持android, MacOS没测试,可能会有问题但原理是正确的 2 uses 3 {$IFDEF POSIX} 4 Posix.Base, 5 Posix.Dlfcn, 6 {$ENDIF} 7 Classes, SysUtils; 8 9 type 10 HMODULE = Cardinal; 11 12 {$IFNDEF FPC} 13 {$IFDEF ANDROID} 14 //Posix.Dlfcn中android版本的dladdr只返回模块名称,不返回全路径 15 //因此需要自己实现dladdr 16 threadvar 17 _ModuleName: MarshaledAString; 18 19 function dladdr(Lib: pointer; info: Pdl_info): Longint; cdecl; 20 var 21 F: Text; 22 s, ss, curnode: string; 23 a1, a2, curbase: UIntPtr; 24 //i: longint; 25 p, pp: PByte; 26 M: TMarshaller; 27 begin 28 Result:=0; 29 _ModuleName:=''; 30 if info = nil then 31 exit; 32 curbase:=0; 33 curnode:=''; 34 Assign(F, '/proc/self/maps'); 35 Reset(F); 36 if IoResult <> 0 then 37 exit; 38 while not Eof(F) do 39 begin 40 // Read the address range info 41 ReadLn(F, ss); 42 p:=PByte(M.AsAnsi(ss, CP_UTF8).ToPointer); 43 // Starting address 44 pp:=p; 45 while not (p^ in [Byte(Ord('-')), Byte(Ord(#0))]) do 46 Inc(p); 47 p^ := Byte(Ord(#0)); 48 49 s := UTF8ToString(MarshaledAString(pp)); 50 a1 := StrToIntDef('$'+s, 0); 51 if a1 > 0 then 52 begin 53 // Ending address 54 Inc(p); 55 pp:=p; 56 while p^ > Byte(Ord(' ')) do 57 Inc(p); 58 p^ := Byte(Ord(#0)); 59 60 s := UTF8ToString(MarshaledAString(pp)); 61 a2 := StrToIntDef('$'+s, 0); 62 63 if a2 > 0 then 64 begin 65 while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace 66 while p^ > Byte(Ord(' ')) do Inc(p); // Skip perms 67 while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace 68 while p^ > Byte(Ord(' ')) do Inc(p); // Skip offset 69 while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace 70 while p^ > Byte(Ord(' ')) do Inc(p); // Skip dev 71 while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace 72 // inode 73 pp:=p; 74 while p^ > Byte(Ord(' ')) do 75 Inc(p); 76 p^ := Byte(Ord(#0)); 77 78 s := UTF8ToString(MarshaledAString(pp)); 79 80 if s <> '0' then 81 begin 82 if s <> curnode then 83 begin 84 curnode:=s; 85 curbase:=a1; 86 end; 87 88 if (UIntPtr(Lib) >= a1) and (UIntPtr(Lib) < a2) then 89 begin 90 while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace 91 // File name 92 if p^ = Byte(Ord('/')) then 93 begin 94 _ModuleName:=MarshaledAString(p); 95 info^.dli_fname:=MarshaledAString(_ModuleName); 96 info^.dli_fbase:=pointer(curbase); 97 info^.dli_sname:=nil; 98 info^.dli_saddr:=nil; 99 Result:=1; 100 end; 101 break; 102 end; 103 end; 104 end; 105 end; 106 end; 107 Close(F); 108 end; 109 {$ELSE} 110 function dladdr(Lib: pointer; info: Pdl_info): Longint; cdecl; 111 begin 112 Result := Posix.Dlfcn.dladdr(UIntPtr(Lib), info^); 113 end; 114 {$ENDIF} 115 {$ENDIF} 116 117 {$IFDEF POSIX} 118 function GetModuleFileName(hLib: HMODULE):string; 119 var 120 dlinfo: dl_info; 121 IsLib: Boolean; 122 begin 123 if hLib=0 then 124 hLib := HMODULE(@GetModuleFileName); 125 126 dladdr(pointer(hLib), @dlinfo); 127 Result := UTF8ToString(dlinfo.dli_fname); 128 end; 129 {$ENDIF} 3. 实现android版的GetModuleHandle有了上面的dladdr实现,其实GetModuleHandle只是由原来通过地址信息获得路径名,逆处理为由路径名获取地址信息,而首地址即使so加载到内存后的句柄。
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论