Delphi DLL与其他编程语言兼容

WeG*_*ars 3 delphi fastmm

我想构建一个DLL,导出返回字符串的函数.这个DLL应该与其他编程语言一起使用!! 我找到了各种令人讨厌的解决方案/黑客,最好的方法是让我的函数返回Pchar,然后调用同一DLL中包含的另一个函数(让我们称之为ReleaseMemory)来释放为PChar保留的内存.

无论如何,最近我发现了FastShareMem库.它说它可以完全按照我想要的方式完成调用ReleaseMemory.在另一边FastMM似乎做同样的,只要DLL和应用程序使用FastMM内存管理器.这会立即杀死使用FastMM作为我的通用DLL的内存管理器的机会.对?

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

FastShareMem(http://www.codexterity.com/fastsharemem.htm),Delphi 7中,Windows XP的32位,视窗7 64位

Rob*_*edy 8

如果你返回一个Delphi string,那么你的DLL将不能与其他编程语言一起使用,因为没有其他编程语言使用Delphi的字符串类型.如果类型不相同,那么如何分配内存并不重要.如果您正在处理文本,请遵循Windows API的模型并使用普通的旧字符指针.

你找到的解决方案 - 返回一个指针,然后为你的DLL提供另一个函数来释放内存 - 不是一个黑客,并不是很讨厌.这是一个非常普通的解决方案,当他们看到它时,没有人会使用你的DLL.该FormatMessageAPI函数使用了类似的模式:它分配一个字符串给你,并指定了它分配的字符串必须被释放LocalFree.

只要你是一致的并且你的DLL的消费者可以使用它,你使用什么内存管理器并不重要.一种方法是分配和释放的字符串,如指定的Windows API函数LocalAllocLocalFree,或SysAllocStringSysFreeString.另一种方法是永远不分配任何东西 - 如果调用者需要你返回一个字符串,调用者提供缓冲区并告诉你它有多大.如果缓冲区太小,则返回所需的大小,以便调用者可以重新分配缓冲区并重新调用该函数.举个例子,请参阅GetLongPathName.

FastSharemem对Delphi的内存管理器如何工作提供了很长的解释,然后它说你可以通过在程序中简单地使用该单元来避免所有麻烦.但请记住我上面所说的:你的DLL的消费者需要能够使用你使用的相同内存管理器.当您的DLL的使用者不是用Delphi编写时,它就不能使用FastSharemem单元.FastSharemem在一个同质的Delphi环境中运行良好,但它在混合环境中使用时遇到了与任何其他内存管理器相同的陷阱.


小智 6

您正在混合两种不同的场景:

  1. 使用Delphi DLL的Delphi应用程序
  2. 任何使用Delphi DLL的应用程序

在第一种情况下,除非你混合Delphi版本或做一些奇怪的事情,内存管理器是相同的,编译器也是如此.因此,有共享内存管理器的方法,然后编译器能够正确处理分配/解除分配.这就是FastMM和FastShareMem都可以工作的情况 - 而且只有这一个.

在第二种情况下,应用程序和DLL将使用不同的内存管理器,可能是非常不同的内存管理器,并且通常无法共享一个.在这种情况下,最好的方法是永远不要返回在DLL内部分配的PChar,即使你提供了一个释放函数,因为你不能确定调用语言将在以后与你的PChar一起做什么,如果调用者有机会在编译器/解释器之前调用正确的释放例程.COM在你说的方式上有所作为,但它通过自己的内存管理器强制执行内存分配/释放,因此它是安全的.您不能使用普通的DLL强制执行它,因此它不安全.

最好的方法是让调用语言通过一个足够大的缓冲区,并在那里写你的PChar.当然,您需要有一些方法告诉调用者缓冲区的大小.这就是Windows本身的工作方式,并且有很好的理由让他们做出这样的选择.

  • 问题是那些不了解指针但又可以传递缓冲区的语言,这些缓冲区是自动管理的.恕我直接让调用者管理它的内存并操纵已经分配的缓冲区要好得多,而不是分配一个并要求调用者释放它,特别是如果你不能像COM那样强制执行你的onw数据类型.代码可能有错误,但有些技术比其他技术更容易引入错误. (2认同)