在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. HashCode equals

    HashCode: hashcode就是一个签名.当两个对象的hashcode一样时,两个对象就有可能一样.如果不一样的话两个对象就肯定不一样.一般用hashcode来进行比较两个东西是不是一样的,可 ...

  2. 菜鸟-教你把Acegi应用到实际项目(9)-实现FilterInvocationDefinition

    在实际应用中,开发者有时需要将Web资源授权信息(角色与授权资源之间的定义)存放在RDBMS中,以便更好的管理.事实上,我觉得一般的企业应用都应当如此,因为这样可以使角色和Web资源的管理更灵活,更自 ...

  3. eclipse 调试时出现 Error: [Errno 10013]

    法1: 端口占用错误.换个端口即可. 新端口 在 8001到15536之间的任意值. 法2: windows下查看哪个程序占用端口 netstat -ano | findstr “8080”  找到p ...

  4. 【转】一个URL编码和解码的C++类

    下面的代码实现了一个用于C++中转码的类strCoding.里面有UTF8.UNICODE.GB2312编码的互相转换. .H文件: #pragma once #include <iostrea ...

  5. SICP 1.1-1.5

    1.1 a = b = nil 1.2 (/ (+ (- (- (+ (/ ))))) (* (- ) (- )) 1.3 a = b = nil 1.4... 1.5 (define (p) (p) ...

  6. 土法炼钢:怎么实现一个简单的B+Tree In-Disk

    1. 写在前面 说起B+树,大家应该都很熟悉.B+树是一种平衡的多路搜索树,广泛在操作系统和数据库系统用作索引.相比于内存的存取速度,磁盘I/O存取的开销要高上几个数量级.而将B+树用作索引时,它可以 ...

  7. 学习练习 java 二分查找法

    package com.hanqi; import java.util.*; public class Test5 { public static void main(String[] args) { ...

  8. CSS 宝库

    Cascading Style Sheets, 层叠样式表单或者层叠样式表.简称CSS. 目的是为了表现HTML或者XML的样式. 可以做到网页内容和表现的分离.可以说,CSS是一种表现语言. h5禁 ...

  9. 【EF 2】浅谈ADO数据模型生成串(二):数据库连接串分析

    导读:上篇博客中介绍了ADO生成串的前一部分,本篇博客结合报错,接着介绍剩下的部分. 一.代码展示 <span style="font-family:KaiTi_GB2312;font ...

  10. angular 页面加载时可以调用 函数处理

    转载于 作者:海底苍鹰地址:http://blog.51yip.com/jsjquery/1599.html 我希望页面加载的时候,我能马上处理页面的数据,如请求API .... 所以这样设置 在某个 ...