DLL 参数为string类型详解

如果,就是你在Delphi当中使用的DLL。那么可以直接返回ARRAY   OF   CHAR。  
   
  这种类型是建立在全局堆上的,不会被收回,而且有引用计数保证在无人使用的时候收回。  
   
  如果你的DLL要被其他开发工具开发的程序共用的,那么不能返回ARRAY   OF   CHAR,你只能返回Pointer,并且要copy一个副本返回,否则会被收回导致指针无效。  
   
  通常,需要返回一个复杂的数据块我们不是用返回值来返回的,除非是建立在堆栈中的数据,比如一个结构。需要返回复杂数据,通常是调用者传入一个指针和缓冲区大小的整数值。函数将内容复制到调用者给出的缓冲区中,这对于动态长度的数据特别合适。为什么这么做呢?因为如果是返回值返回缓冲区指针,那么意味着是函数创建的缓冲区,而调用者却有释放缓冲区的义务,这是不合理的,因为不同的编译器产生的缓冲区结构是不一样的,会造成内存泄露。基本原则是谁创建谁释放,所以,通常由调用者传入一个缓冲区指针,而函数仅仅使用缓冲区。函数返回值通常指出缓冲区中填入了多少数据,或者指出一个所需的正确缓冲区的大小。  
   
  还有一种作法,就是你把ARRAY   OF   CHAR类型包装出一个interface返回值是包装好的对象的interface,这种做法符合对象原则,interface不用担心回收问题,它会自动收回的,对于调用者来说,使用interface是很方便的。  
   
  如果传送的数据结构特别大,复制很费时。那么我们一般使用Stream。  
   
  Stream的问题是没有统一的标准,你应该封装一个Stream的interface返回给调用者,使用Stream的方式可以避免数据被反复的复制,使用Stream可以大大提高效率。  
   
  比如将一个文件数据从Socket发送出去,如果直接打开文件复制内容到内存中,然后用Socket发送是费时的,使用Stream可以让Socket自己直接去从文件中复制数据,这样减少一次数据复制过程。此外如果文件需要加密传送,那么使用Stream就特别有效了。  
   
  上面漏了一点,就是返回值直接使用array   of   char时候,需要添加ShareMem单元在uses第一位置,同时发布的时候带上BORLANDMM.DLL这个DLL。  
   
  我不认为这是必须的,可能是为了兼容win95才这么麻烦吧。  
   
  默认的存储管理器源代码在source/rtl/sys/getmem.inc中。Delphi内存管理器用VirtualAlloc分配内存,内存分配表用LocalAlloc分配的  
   
  但是,我觉得在win32上不区分局部堆和全局堆,只有老的win16才会造成麻烦。DLL如果又调用了一次内存初始化的函数,那么也没关系,只要DLL一直在内存中不卸载,也不会造成麻烦。当然DLL如果是动态加载的,那么DLL卸载的时候很可能释放了正在exe中使用的内存块。  
   
  这个问题,还需要查证。如果不是动态加载DLL,那么我想什么问题都不会有。  
   
  DLL卸载或者exe退出的时候就会释放所有在DLL和EXE中分配的内存。  
   
  这样的话就很罗嗦,不过也正常,DLL都释放了,从DLL调用得到的内存还会存在吗?只要稍微注意一下使用方式就没事了。  
   
  但是,在win32下,绝对不会因为你在DLL中分配内存导致exe中不可用的情况出现。所以感觉那个ShareMem在win32下没有什么用处,除非是为了防止DLL卸载造成分配内存不可用。

对于string来说,他就是一个array   of   char,结构完全一致。  
   
  我上面说了,如果返回值是string这样的在全局堆分配的对象,那么只要DLL不卸载不会产生任何问题。  
   
  在你的函数中,你用了一个局部变量D来存放从DLL中返回的string。这个局部变量会在函数结束时自动释放它所引用的string对象的计数(这是编译器自动生成的代码),而这时DLL已经被卸载了,它所分配的内存已经不存在了,当然会出错!   
    
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值