Delphi写DLL要注意的问题 (转)

摘要:
今天,我写了一个dll供调用。网在我编写了dll之后,我使用delphi对其进行了测试。有一个错误,更不用说对.net的调用了。检查后,我们发现参数和返回值使用了字符串类型。后来,我们看到“Delphi编写DLL返回字符串Net调用”。如果调用者和被调用者都是Delphi程序,并且您希望使用字符串或动态数组作为参数,那么双方项目文件的第一个包含单元必须是ShareMem。由于其扩展名,它表明该文件仅由Delphi/C++Builder使用。

今天写一个dll准备给.net调用, dll写出之后给用delphi测试一下, 居然出错, 更别说给.net调用了.查来查去原来是参数和返回值使用string类型, 后面看了'Delphi 编写 DLL 返回字符串,.net 调用。' 这篇文章才解决, 顺便也收藏了一下,原来delphi写的dll有这么多限制的.

 

这一点我们需要注意  
a. 参数和返回值为string、动态数组类型时,DLL和EXE都要把ShareMem作为.dpr工程的第一个单元引用。当然最好是不要使用 string、动态数组类型,可以改用PChar、数组指针类型,如果是混合语言编程使用的话,就一定不能用string、动态数组类型。这样做的原因是 DLL和EXE的内存管理器(MemoryManager)不是一个,而string、动态数组类型是通过引用计数由Delphi自动进行内存管理的,它 何时分配何时释放,我们不能显式的知道的,DLL分配而EXE释放的话,这样就出问题了。用ShareMem就是为了让它们统一使用一个内存管理器进行内 存分配释放。 关于DLL和EXE内存管理器不同这一点,非常重要! 
b.DLL和EXE的VCL类体系不是一个,它们各自有一套,因此,从EXE传递过去的对象,要在DLL中用is判断类型和as作类型转换,那都不能得到期望的结果。 如果是bpl,就不会有这个问题  
c.DLL中应用ADO、窗体(模态、非模态、MDI子窗体)、线程等的一些相关问题与今天的主题关系不大,就不作多讲了。参考DLL的详细论述请参考《Windows核心编程》第19、20章。

========================================================

对使用Delphi制作DLL复用文件的建议

在公司里有一些需要制作DLL的场合,因为熟悉、方便和简易,大多数使用Delphi来制作。现在就这个主题提出一些个人建议。

尽 量使用标准DLL接口。指的是传递的参数类型及函数返回类型不能是Delphi特有的,比如string(AnsiString),以及动态数组和含有这 些类型成员的复合类型(如记录),也不能是包含有这些类型成员数据成员的对象类型,以避免可能的错误。如果使用了string类型或动态数组类型,且调用 方不是Delphi程序,则基本上会报错。如果调用方是Delphi但调用方或被调用方没有在工程文件的第一包含单元不是ShareMem,也可能会出 错。

如果调用方是Delphi应用程序,则可能可以使用不包含禁止类型(string, 动态数组)数据成员的对象作为参数或返回值,但也应尽量避免。

如果调用方与被调用方都是Delphi程序,而且要使用string或动态数组作参数,则双方工程文件的第一包含单元必须是ShareMem。(C++Builder程序的情况可能与此相同,不过没有测试过。)

如果调用方不是Delphi程序,则string、动态数组、包含string或动态数组的复合数据类型及类实例,都不能作为参数及返回值。

因此,为了提高DLL的复用范围,避免可能存在的错误,应当使用标准WIN32 API标准参数类型,以前使用string的变量,可以使用PChar(s)转换。动态数组则转换为指针类型(@array[0]),并加上数组的长度。

如果因为调用方与被调用方都是Delphi程序,为了编写方便,不想进行上述转换,则推荐使用运行时包的形式。运行时包可以保证动态分配数据的正确释放。这样因为其扩展名(.bpl),显出该文件仅限于Delphi/C++Builder使用(不象DLL)。

其 次,尽量避免使用overload的函数/过程作输出,如果同一操作有多个方式,则可以让函数/过程名有少许差别,类似于Delphi中的 FormatXXXX、CreateXXXX等函数及方法,如CreateByDefaultFile, CreateDefault。

最 后,作为DLL的提供者,应当提供直接编程的接口文件,如Delphi中的.pas或.dcu(最好是.pas,因为可以有注释)、C及C++中的.h 和.lib。而不是让使用者们自己创建。如果非要有overload的函数/过程,这一点显得特别重要。另外,作为Delphi应用,提供的.pas文件 可以是提前连接的(使用external指定DLL中的输出函数),也可以是后期连接的(使用LoadLibrary、 GetProcAddress),DLL提供者提供编程接口文件,既显得正式(或HiQoS),又有保障。

免责声明:文章转载自《Delphi写DLL要注意的问题 (转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SAE java应用读写文件(TmpFS和Storage)用gulp清除、移动、压缩、合并、替换代码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java Properties 类读取配置文件信息

在我们平时写程序的时候,有些参数是经常改变的,而这种改变不是我们预知的。比如说我们开发了一个操作数据库的模块,在开发的时候我们连接本地的数据库那么IP,数据库名称,表名称,数据库主机等信息是我们本地的,要使得这个操作数据的模块具有通用性,那么以上信息就不能写死在程序里。通常我们的做法是用配置文件来解决。 各种语言都有自己所支持的配置文件类型。比如Pytho...

手把手教你实现热更新功能,带你了解 Arthas 热更新背后的原理

摘自:https://www.cnblogs.com/goodAndyxublog/p/11880314.html 手把手教你实现热更新功能,带你了解 Arthas 热更新背后的原理 文章来源:https://studyidea.cn/java-hotswap 一、前言# 一天下午正在摸鱼的时候,测试小姐姐走了过来求助,说是需要改动测试环境 mock...

Java学习第十五章 之 Map、可变参数、Collections

1 /* 2 3 Map:存储键值对 4 5 键不能重复存储,值可以重复 6 7 每一个键对应一个值 8 9 方法: 10 11 v put(K key , V value)将指定的键和值添加到集合中 12 13 v get(Object o...

python之SQLAlchemy

ORM介绍 orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型...

Slf4j MDC机制

转自:  https://www.liangzl.com/get-article-detail-572.html MDC 简介 MDC ( Mapped Diagnostic Contexts ),它是一个线程安全的存放诊断日志的容器。 Logback设计的一个目标之一是对分布式应用系统的审计和调试。在现在的分布式系统中,需要同时处理很多的请求。如何来很好...

Guava LoadingCache不能缓存null值

测试的时候发现项目中的LoadingCache没有刷新,但是明明调用了refresh方法了。后来发现LoadingCache是不支持缓存null值的,如果load回调方法返回null,则在get的时候会抛出异常。 通过几个例子开看这个问题: public void test_loadNull() { LoadingCache<String,...