简体   繁体   English

在delphi DLL中使用delphi应用程序的内存管理器(无需重新编译应用程序)

[英]Using delphi application's memory manager in a delphi DLL (without recompiling the application)

I need to write a DLL (using Delphi) which is dynamically loaded into delphi applications and makes RTTI queries (typical operation is to obtain string values for control properties). 我需要编写一个DLL(使用Delphi),该DLL将被动态加载到delphi应用程序中并进行RTTI查询(典型的操作是获取控件属性的字符串值)。 The classic problem is that passing strings (and objects) between application and DLL is problematic due to different memory managers used in both (this might lead to memory issues, eg DLL's memory manager would try to free the memory allocated by Application's memory manager). 典型的问题是,由于在两者之间使用不同的内存管理器,因此在应用程序和DLL之间传递字符串(和对象)存在问题(这可能会导致内存问题,例如DLL的内存管理器将尝试释放由应用程序的内存管理器分配的内存)。

Is there a way to set DLL's memory manager to application's memory manager in a way that would not depend on delphi version? 有没有一种方法可以将DLL的内存管理器设置为应用程序的内存管理器,而不依赖于delphi版本? Any thoughts? 有什么想法吗?

October 2010 edit: 2010年10月编辑:

Since interest to this topic is almost lost - I'll describe the (quite poor) solution which I ended up with so that others would understand why I didn't accept any of the proposed answers. 由于对该主题的兴趣几乎消失了-我将描述最终导致的(相当差的)解决方案,以便其他人理解为什么我不接受任何建议的答案。

So a hacky way to perform something like this would be to find RVA of MemoryManager structure (refer to implementation part of System.pas) and hardcode in the DLL. 因此,执行此类操作的一种简便方法是在MemoryManager结构中找到RVA (请参阅MemoryManager实现部分)并在DLL中进行硬编码。 This way, DLL would be able to set its private memory manager to be the same as that of the application it is being loaded into. 这样,DLL可以将其专用内存管理器设置为与正在加载的应用程序相同。 It works with some limitations and issues; 它具有一些局限性和问题; anyway - it is very Delphi compiler & linker options dependent. 无论如何-这是非常依赖Delphi编译器和链接器选项的。

Though it is not an answer I was searching for - I do not expect anything better than this. 尽管这不是我一直在寻找的答案-我期望没有比这更好的了。

Use the same memory manager for your application and your DLLs. 为您的应用程序和DLL使用相同的内存管理器。

For recent version of Delphi that includes the new FastMM memory manager, use SimpleShareMem as the 1st unit in both your application and the DLL projects. 对于包含新的FastMM内存管理器的Delphi的最新版本,在应用程序和DLL项目中都将SimpleShareMem用作第一单元。

Or download the full FastMM4 from SourceForge , set the Flags in FastMM4Options.Inc (ShareMM, ShareMMIfLibrary, AttemptToUseSharedMM) and put FastMM4 as the 1st unit in both the application and the DLLs projects. 从SourceForge下载完整的FastMM4 ,在FastMM4Options.Inc(ShareMM,ShareMMIfLibrary,AttemptToUseSharedMM)中设置标志,并将FastMM4作为应用程序和DLL项目中的第一单元。

Another approach, would be to use COM. 另一种方法是使用COM。 It would not be specific to a version of Delphi, but would require you to create and implement a com interface in your main application which provided the necessary services to your DLL. 它不是特定于Delphi的版本,而是需要您在主应用程序中创建并实现com接口,该接口为DLL提供了必要的服务。 After you loaded your DLL you would then pass the interface reference to the DLL and use it instead. 加载DLL之后,您可以将接口引用传递给DLL并使用它。 The other advantage of this approach is that any language that can create DLL files and use com interfaces would be able to act as a plugin. 这种方法的另一个优点是,任何可以创建DLL文件并使用com接口的语言都可以充当插件。 Of course Delphi would be the tool of choice, mainly because it makes both requirements painless. 当然,Delphi将是首选的工具,主要是因为它使这两个要求都变得轻松。

I am not sure what RTTI calls your making from your DLL, but the best place for those are inside your application to avoid any problems in translation that can occur between Delphi versions when there is a compiler mismatch between dll and executable. 我不确定RTTI调用您的DLL是什么,但是对于那些DLL来说,最好的选择是在您的应用程序内部,以避免当dll和可执行文件之间的编译器不匹配时,在Delphi版本之间可能发生的翻译问题。

Here's a nice article that has some recommendations: 这是一篇不错的文章,其中包含一些建议:

http://www.codexterity.com/memmgr.htm http://www.codexterity.com/memmgr.htm

I also found this: 我也发现了这一点:

http://sourceforge.net/projects/fastmm/ http://sourceforge.net/projects/fastmm/

I haven't tried either of the libraries they recommend. 我没有尝试过他们推荐的任何一个库。 It might get you version independence, it might not. 它可能使您具有版本独立性,但可能没有。 If you're wanting to distribute the DLL and support different Delphi versions, that might be problematic. 如果要分发DLL并支持不同的Delphi版本,则可能会出现问题。 One option would be to compile a version for several of the major releases. 一种选择是为多个主要版本编译一个版本。

Note: It's unclear when FastSharemem was last updated; 注意:尚不清楚上一次更新FastSharemem的时间。 it may be obsolete. 它可能已过时。

Ok, as there aren't any alternatives - the hacky solution of my own would be the answer: 好的,因为没有其他选择-我自己的hacky解决方案将是答案:

  1. find RVA of MemoryManager structure (refer to implementation part of System.pas ) 找到的MemoryManager结构的RVA(指的实现部分System.pas
  2. Use it in your DLL to set its own memory manager to be the same as that of the application it is being loaded into. 在DLL中使用它可以将其自己的内存管理器设置为与要加载到的应用程序相同。

As already stated in the body of my question - it works with some limitations and is very fragile in scope of compiler & linker options 正如我的问题中已经提到的那样-它有一些限制,并且在编译器和链接器选项的范围内非常脆弱

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM