在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 代码

 //可支持android和linux
uses
{$IFDEF FPC}
{$IFDEF UNIX}
//BaseUnix, Unix,
dl;
{$ENDIF}
{$ENDIF}
9 type
10 HMODULE = Cardinal;
{$IFDEF FPC}
{$IFDEF UNIX}
function GetModuleFileName(hLib: HMODULE):string;
var
dlinfo: dl_info;
IsLib: Boolean;
begin
if hLib= then
hLib := HMODULE(@GetModuleFileName); dladdr(Pointer(hLib), @dlinfo);
Result:=string(dlinfo.dli_fname);
end;
{$ENDIF}
{$ENDIF}

2.2 delphi XE7 代码

 //支持android, MacOS没测试,可能会有问题但原理是正确的
uses
{$IFDEF POSIX}
Posix.Base,
Posix.Dlfcn,
{$ENDIF}
Classes, SysUtils; type
HMODULE = Cardinal; {$IFNDEF FPC}
{$IFDEF ANDROID}
//Posix.Dlfcn中android版本的dladdr只返回模块名称,不返回全路径
//因此需要自己实现dladdr
threadvar
_ModuleName: MarshaledAString; function dladdr(Lib: pointer; info: Pdl_info): Longint; cdecl;
var
F: Text;
s, ss, curnode: string;
a1, a2, curbase: UIntPtr;
//i: longint;
p, pp: PByte;
M: TMarshaller;
begin
Result:=;
_ModuleName:='';
if info = nil then
exit;
curbase:=;
curnode:='';
Assign(F, '/proc/self/maps');
Reset(F);
if IoResult <> then
exit;
while not Eof(F) do
begin
// Read the address range info
ReadLn(F, ss);
p:=PByte(M.AsAnsi(ss, CP_UTF8).ToPointer);
// Starting address
pp:=p;
while not (p^ in [Byte(Ord('-')), Byte(Ord(#))]) do
Inc(p);
p^ := Byte(Ord(#)); s := UTF8ToString(MarshaledAString(pp));
a1 := StrToIntDef('$'+s, );
if a1 > then
begin
// Ending address
Inc(p);
pp:=p;
while p^ > Byte(Ord(' ')) do
Inc(p);
p^ := Byte(Ord(#)); s := UTF8ToString(MarshaledAString(pp));
a2 := StrToIntDef('$'+s, ); if a2 > then
begin
while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace
while p^ > Byte(Ord(' ')) do Inc(p); // Skip perms
while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace
while p^ > Byte(Ord(' ')) do Inc(p); // Skip offset
while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace
while p^ > Byte(Ord(' ')) do Inc(p); // Skip dev
while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace
// inode
pp:=p;
while p^ > Byte(Ord(' ')) do
Inc(p);
p^ := Byte(Ord(#)); s := UTF8ToString(MarshaledAString(pp)); if s <> '' then
begin
if s <> curnode then
begin
curnode:=s;
curbase:=a1;
end; if (UIntPtr(Lib) >= a1) and (UIntPtr(Lib) < a2) then
begin
while p^ <= Byte(Ord(' ')) do Inc(p); // Whitespace
// File name
if p^ = Byte(Ord('/')) then
begin
_ModuleName:=MarshaledAString(p);
info^.dli_fname:=MarshaledAString(_ModuleName);
info^.dli_fbase:=pointer(curbase);
info^.dli_sname:=nil;
info^.dli_saddr:=nil;
Result:=;
end;
break;
end;
end;
end;
end;
end;
Close(F);
end;
{$ELSE}
function dladdr(Lib: pointer; info: Pdl_info): Longint; cdecl;
begin
Result := Posix.Dlfcn.dladdr(UIntPtr(Lib), info^);
end;
{$ENDIF}
{$ENDIF} {$IFDEF POSIX}
function GetModuleFileName(hLib: HMODULE):string;
var
dlinfo: dl_info;
IsLib: Boolean;
begin
if hLib= then
hLib := HMODULE(@GetModuleFileName); dladdr(pointer(hLib), @dlinfo);
Result := UTF8ToString(dlinfo.dli_fname);
end;
{$ENDIF}

3. 实现android版的GetModuleHandle

有了上面的dladdr实现,其实GetModuleHandle只是由原来通过地址信息获得路径名,逆处理为由路径名获取地址信息,而首地址即使so加载到内存后的句柄。

Delphi For Android 开发笔记-附:如何Delphi中同时实现Windows、Android版的GetModuleFileName函数的更多相关文章

  1. 《ArcGIS Runtime SDK for Android开发笔记》——(4)、基于Android Studio构建ArcGIS Android开发环境

    1.前言 2015年1月15日,发布ArcGIS Runtime SDK for Android v10.2.5版本.从该版本开始默认支持android studio开发环境,示例代码的默认开发环境也 ...

  2. 《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)(转)

    1.前言 在上一篇的内容里我们介绍了基于Android Studio构建ArcGIS Runtime SDK for Android开发环境的基本流程,流程中我们采用的是基于Gradle的构建方式,在 ...

  3. 《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析

    1.前言 Android Studio 是第一个Google官方的 Android 开发环境.其他工具,例如 Eclipse,在 Android Studio 发布之前已经有了大规模的使用.为了帮助开 ...

  4. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

  5. 【转】Android开发笔记——圆角和边框们

    原文地址:http://blog.xianqu.org/2012/04/android-borders-and-radius-corners/ Android开发笔记——圆角和边框们 在做Androi ...

  6. 《ArcGIS Runtime SDK for Android开发笔记》

    开发笔记之基础教程 ArcGIS Runtime SDK for Android 各版本下载地址 <ArcGIS Runtime SDK for Android开发笔记>——(1).And ...

  7. [APP] Android 开发笔记 003-使用Ant Release 打包与keystore加密说明

    接上节 [APP] Android 开发笔记 002 5. 使用ant release 打包 1)制作 密钥文件 release.keystore (*.keystore) keytool -genk ...

  8. Android开发笔记:打包数据库

    对于数据比较多的控制一般会加入SQLite数据库进行数据存储,在打包时这些数据库是不自动打包到apk中的,如何创建数据库呢 方法1:将创建数据库的sql语句在SQLiteHelper继承类中实现,在第 ...

  9. Android开发笔记--hello world 和目录结构

    原文:Android开发笔记--hello world 和目录结构 每接触一个新东西 都有一个hello world的例子. 1.新建项目 2.配置AVD AVD 没有要新建个,如果不能创建 运行SD ...

随机推荐

  1. (转)C#picturebox控件使用

    PictureBox是C#常用图片空间,本文是学习中搜集网络资料的一些整理和记录 1,PictureBox加载图片 using System.Drawing; //方式1,从图片文件载入 //下面的路 ...

  2. history.back(-1)和history.go(-1)的区别

    history.back(-1):直接返回当前页的上一页,数据全部消息,是个新页面 history.go(-1):也是返回当前页的上一页,不过表单里的数据全部还在 返回到指定连接:document.l ...

  3. 在Visual Studio 2013上安装SQLite designer components

    最近搞一个WinCE项目,要用到SQLite.看人家都能直接在Visual Studio上连接SQLite.我也按照他们的方法安装了最新的Setups for 32-bit Windows (.NET ...

  4. [工具] 如何利用Notepad++去除重复行

    问题: 需要去除重复数据, 例如: 解决方案: 1. 打开notepad++: 2. 如果没有找到"TextFx" 选项, 需要先安装该插件. 依次打开"插件" ...

  5. Flex 列表控件中的操作

    主要操作包括:显示提示,使用图标,编辑列表条目中数据. 1.使用数据提示: 当鼠标停留在条目上时,可以显示该条目的相关数据提示. 当利用滚动条时,可以显示滚动条的相关提示. 在列表控件中使用showD ...

  6. .NET MVC4.0与CA对接

    1.改web.confog 2.引用CA提供的 dll 3.在controller层加个方法,记得加上授权认证的特性,获取信息 [Authorize] publi void calogin() { H ...

  7. 洛谷P1983 车站分级

    P1983 车站分级 297通过 1.1K提交 题目提供者该用户不存在 标签图论贪心NOIp普及组2013 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 求帮忙指出问题! 我这么和(diao ...

  8. VC 宏与预处理使用方法总结

    目录(?) C/C++ 预定义宏^ C/C++ 预定义宏用途:诊断与调试输出^ CRT 和 C 标准库中的宏^ NULL 空指针^ limits.h 整数类型常量^ float.h 浮点类型常量^ m ...

  9. Multithreading annd Grand Central Dispatch on ios for Beginners Tutorial-多线程和GCD的入门教程

    原文链接:Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial Have you ever written a ...

  10. Oracle笔记 十一、PL/SQL函数和触发器

    --创建函数 create or replace function add_sal(sSal number) return number is begin if (sSal > 5000) th ...