早期的 delphi 曾经出扒李过一个 delphi for linux 版本,被称为 kylix,用于开发 linux 应用,其后因多种原因该版本没有进一步的开发完善。
在最新发布的 DELPHI XE 10.2(TOKYO),可以开发多种平台的应用程序,其中就包括 linux,脊空以下是相关的特性介春野迟绍:
本文用通俗易懂的语言介绍Linux平台上共享对象库(SO)的基本概念及主要优点 通过剖析在耐陪Delphi for Linux中应用SO与在Delphi for Windows中应用DLL的异同 以编程实例讲述了Linux平台的SO库文件的组成 SO库文件的函数重载 特殊编译指令 采用Delphi for Linux创建SO的编程规则 使用前的Linux系统设置 以及在Delphi for Linux中用隐式或显式链接方法装入和使用SO函数的基本方法 经验及技巧 并对应用SO可能出现的问题进行了探讨和分析 共享对象库基本概念Delphi for Linux是Borland公司推出的基于Linux平台的 面向对象的可视化开发工具 是目前Linux平台上很好的应用开发工具 Delphi for Linux也称Kylix 大家用Kylix开发Linux应用程序时 可能使用过Linux *** 作系统本身带的大量SO文件 SO是一种特殊的运行文件 包含若干方法 对象和资源 它不能直接运行 但可以被Kylix应用程序或其它可执行文件动态调用 SO文件扩展名为 so 编译前源文件扒让扩展名为 dpr 本文所举例子均在Red Hat Linux 及Kylix 环境下调试编译通过 并可正常运行 图 是Kylix主程序与SO库的层次关系图 从中可看出使用SO库有以下几个优点 图 Kylix主程序与SO库的层次关系图 ◆ 多个Kylix程序或它的多个单元文件可通过接口共用一个SO库文件 另一方面 某一个Kylix程序 可通过多个接口使用多个SO库文件 这样 SO变成一种可共用的资源 实现真正的 资源共享 大大缩小了Kylix应用程序的执行代码 增强了软件的可重用性 ◆ 将SO文件作为Kylix应用程序的公共调用模块设计时 由于其独立于应用程序 软件升级春亩局时只需修改SO库文件及编译SO 无需更改及重编译Kylix应用主程序 ◆ 不仅可使用Kylix编写SO库 还可使用C或C++等常用语言来编写 只要遵循特定的接口规范 共享对象库的创建 SO库文件的构成SO库文件和Kylix标准单元文件的内部结构基本相同 也有声明 实现及初始化部分 区别之一在于SO库只是其它程序可以调用的方法(包括函数及过程)集合 区别之二库程序以library关键字而非project开头启动其项目文件 库程序包含有exports语句 其列出要向外部提供的导出函数及过程 下面是SO库文件代码的简单例子 用以说明其构成 library MyFirstSO uses SysUtils classes { Delphi for Windows 中引用类库为Windows }function Add (A Char B Char) Integer cdecl overload begin Result := Ord (A) + Ord (B) end function Add (A Integer B Integer) Integer cdecl overload begin Result := A + B end function Double (N Integer) Integer cdeclbegin Result := N * endexports Add (A Integer B Integer) Add (A Char B Char) name AddChar Double SO库文件中的函数重载SO库也可以使用重载函数(即多个函数使用相同名称 不同参数) 使用时需在重载的函数声明后标上overload指令 Kylix可以用原名称导出一个重载函数 在exports从句中表示其参数表 若要导出多个重载函数 则要在exports从句中用name字句指定不同名称 以区别重载 这可从上面的例子MyFirstSO中看出 Add是重载函数 为调用时区分 一个用原函数声明Add导出 另一个用AddChar导出 SO库的特殊编译指令编译后生成的SO库运行文件使用lib前缀和 so扩展名 考虑到实际命名规则与版本和支持符号链 Kylix在Object Pascal语言中引入了几个特殊编译指令 这些在Delphi中没有什么意义 库源文件MyFirstSO dpr编译后产生的执行文件为libMyFirstSO so ◆ $SOPREFIX 改变名称前缀 默认为lib(正常库)或bpl(Kylix包) 用前缀区别两种库是因为Linux的库用单一扩展( so) ◆ $SOSUFFIX 在库名与扩展名之间增加文本 指定版本或其它信息 ◆ $SOVERSION 在扩展名之后增加版本号 ◆ $SONAME 表示相关符号链名 由编译器自动生成 例如 下列代码生成库libsimple so 和符号链libsimple so library simple usesSysUtils Classes //函数定义省略{$SOVERSION }{$SONAME libsimple so }共享对象库的使用Kylix应用程序使用SO库时 可以采用两种方式 一种是隐式链接(Implicit linking) 也称静态装入 另一种是显式链接(Explicit Linking) 也称动态装入 下面分别介绍这两种链接方式的使用方法 技巧及将窗体对象放入SO库的技术 使用前的系统设置自定义SO库建好后 Kylix应用程序调用时会报错 这是因为Kylix找不到新建库 必须对系统进行相关设置 这与在Delphi for Windows中使用DLL库不同 DLL库建好后只需将编译后的DLL文件放到Delphi主程序目录下即可使用 *** 作步骤如下 ◆ 将编译好的SO库文件放到Linux系统库目录/lib或/usr/lib下 或者在Linux系统库路径shell变量LD_LIBRARY_PATH中加入自定义SO库文件所在路径 ◆ 在根用户(root)下 用ldconfig命令刷新库缓冲区 ◆ 对Kylix执行文件使用ldd命令 查看该程序所关联的SO库 隐式链接隐式链接是指在应用程序开始执行时就将SO库文件加载到应用程序中 实现隐式链接并不难 只需在应用程序中加入库函数的声明语句及库的external定义从句 则库函数可以和一般局部函数一样使用 比如 要使用libMyFirstSO so中的Add函数 则只要在应用程序中增加下面语句 function Add (A Integer B Integer) Integer cdecl external libMyFirstSO so 显式链接显式链接是应用程序在执行过程中可根据实际需要随时加载SO库文件 也可以随时卸载SO库文件 还可在运行时进行SO库的切换 而这些是隐式链接无法做到的 与隐式链接相比 显式链接具有更大的灵活性 在Kylix中 要动态装入库和调用导出函数可以用Delphi仿真代码或自然Linux方法 下面分别介绍这两种方法 ( )用Delphi仿真代码动态装入在Windows中动态装入DLL是用Windows API函数—LoadLibrary或Delphi提供的SafeLoadLibrary函数完成的 找到库后 程序调用Windows API函数—GetProcAddress搜索DLL导出函数 若找到匹配 则返回所请求函数指针 并将这个函数指针转换成适当类型和调用 使用完后调用FreeLibrary 从内存中释放库 Kylix中使用Pascal RTL仿真函数实现SO库动态装入 下面的例子只列出Kylix应用程序中与动态链接相关部分 而非完整Kylix单元文件代码 unit DynaForminterfaceusesSysUtils Classes Qcontrols Qforms type TForm = class(TForm)Button : TButtonprocedure Button Click(Sender: TObject)endvar Form TForm implementation{$R * XFM}type TComputeInteger = function (x Integer y Integer) Integer cdecl //调用库函数接口类型定义procedure TForm Button Click(Sender TObject) var Handle Thandle Compute TputeInteger begin Handle:=LoadLibrary( libMyFirstSO so ) //动态装入库 if Handle<>then //找到库 beginCompute:=TputeInteger(GetProcAddress(Handle Add ) //搜索库函数Add 并返回函数指针if Assigned(Compute) then ShowMessage(IntToStr(Compute( )) //使用库函数FreeLibrary(Handle) //释放库 end elseShowMessage( Library not found ) end ( )用Linux自然代码动态装入也可以使用Libc系统单元中的低级Linux函数 这样可使用更多参数 更好地控制系统 使用的Linux函数分别为dlopen(打开并装入库函数) dlsym(搜索库函数) dlclose(释放库) 因此 上例中调用库的代码变为 procedure TForm Button Click(Sender TObject) var Handle Pointer Compute TputeInteger begin Handle:=dlopen( libMyFirstSO so ) //动态装入库 if Handle<>nil then //找到库 beginCompute:=TputeInteger(dlsym(Handle Add ) //搜索库函数Add 并返回函数指针if Assigned(Compute) then ShowMessage(IntToStr(Compute( )) //使用库函数dlclose(Handle) //释放库 end elseShowMessage( Library not found ) end ( )SO库中窗体对象的使用除了包含函数和过程的库之外 还可以将Kylix建立的窗体放在共享对象中 这可以是对话框或其它窗体 生成新的库对象之后 只要在库源文件的声明部分增加对窗体单元文件 lishixinzhi/Article/program/Delphi/201311/24683
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)