前一篇文章介绍了为何要共用内存管理器,有人要问可不可以在编写dll时更通用一些,可以兼顾其它编译器(如果是其它编译器的话,Delphi写的dll不能与其它语言共用内存管理器),采用一定的策略来避免在dll内创建RTL自动管理的数据类型做参数或返回值,这样其它非Delphi的开发语言也可以用了!

完全可以!

一般的策略如下:

1.在主调函数中申请一块空间

2.把这个空间的地址传送给dll

3.dll内部进行逻辑运算,得到结果后把值添到主调函数传递过来的空间上

4.主调函数获取值,根据业务规则对空间进行处理(释放等操作)

在整个工作周期中,申请的内存一直掌握在主调函数的手中,没有给dll任何管理对象的机会!

看一下下面的主调函数申请内存的模板!

在这里需要强调几点:
//.不用共用内存管理器的话,数据类型需要使用Windows标准类型,如PChar!另外在dll中返回结构体时,最好结构体内的成员为基本数据类型,不要成员又是指针,一不小心就会出错!
//.PChar是一个指针,一般在主调函数中申请空间时先申请255,并把地址传入dll,dll进行逻辑处理,处理完毕后进行返回,返回时,长度可能远远小于255,所以在返回时通过一个变参告诉主调,实际只用了N个长度,这时主调在主动清理实际使用的长度!
//.一般在程序中string与PChar都是结合使用,即返回PChar后直接给一个string,这样更方便!但string类型的特殊性(与Java的string类似),直接赋值会出现问题,故需要用Move或CopyMemory进行内存复制工作,对于为什么出现问题,我想单独写一个文章来解释!
type
TGetStr=function(Src: PChar;srcLen: Integer;Buffer: PChar;var Size: Integer):boolean;stdcall; function GetDllStr: string;
var
DllHnd: THandle;
GetStr: TGetStr;
Str,Buf: PChar;
size:integer;
begin
size:=;
DllHnd := LoadLibrary(PChar('project1.dll'));
try
if (DllHnd <> ) then
begin
@GetStr :=GetProcAddress(DllHnd, 'TestFunc');
if (@GetStr<>nil) then
begin
GetMem(Str, size);{分配}
StrPCopy(Str,'asdf');
GetMem(Buf,Size);
try
GetStr(Str,size,buf,size);
result := StrPas(buf);{返回}
finally
FreeMem(Str);{释放}
FreeMem(Buf,Size);
end;
end
else
begin
application.MessageBox(PChar('DLL加载出错,DLL可能不存在!'), PChar('错误'),
MB_ICONWARNING or MB_OK);
end;
end;
finally
FreeLibrary(DllHnd);
end;
end; //dll实现
function AddStr(Src:PChar):string;
begin
result:=Src+'/Liangpei hello!';
end;
function TestFunc(Src: PChar;srcLen: Integer;Buffer: PChar;var Size: Integer):boolean;stdcall;//函数调用协议
var
LocalString:string;
begin
result:=false;
LocalString:=AddStr(Src);//一般字符串传入dll后,均要根据某些业务做一些加工或处理,AddStr就为处理函数
if (Buffer = Nil) or (Size < srcLen) then begin
SetLastError(Byte(Buffer <> Nil) * (*ERROR_MORE_DATA, need more buffer size*) );
Size := srcLen;
Exit;
end;
CopyMemory(Buffer,PChar(LocalString),Min(Size,Length(LocalString)));
Size := srcLen;
Result := true; end; exports
TestFunc;

最新文章

  1. 对JavaScript闭包和原型理解
  2. 【linux】su、sudo、sudo su、sudo -i的用法和区别
  3. Linux sed 批量替换多个文件中的字符串
  4. Java中String类的方法及说明
  5. MyBatis crud操作
  6. mac os x用macport安装redis
  7. 【py分析】使用SGMLParser分析淘宝html
  8. Python 字典(Dictionary) setdefault()方法
  9. 时序列数据库武斗大会之 TSDB 名录 Part 1
  10. linux 上不去网
  11. JavaScript的68个技巧一
  12. Windows Azure HDInsight 现已正式发布!
  13. Java String 类的 equals 和 ==
  14. List&lt;Object&gt;中,以Object的某一属性值为参照进行排序,选取最大记录的解决办法
  15. 对Java配置文件中敏感信息进行加解密的工具类
  16. SpringBoot2.0+Mybatis-Plus3.0+Druid1.1.10 一站式整合
  17. 游戏编程算法与技巧 Game Programming Algorithms and Techniques (Sanjay Madhav 著)
  18. 总结sql中in和as的用法
  19. 2018-2019-2 网络对抗技术 20165320 Exp4 恶意代码分析
  20. 手把手教你用CAB发布OCX的简单办法

热门文章

  1. 使用solr报错
  2. [转]Cross-type joins in Elasticsearch
  3. JavaScript中的内置对象-8--4.date对象中-获取,设置日期时间的方法; 获取,设置年月日时分秒及星期的方法;
  4. 20165228 2017-2018-2 《Java程序设计》第1周学习总结
  5. 【重要】NOI-1.2-10-字符串大小
  6. Unity射线检测的用法总结
  7. CSS3 transform变形(2D转换)
  8. acm 2072
  9. 网站基于vs,复选框,单选款
  10. 异构环境oracle数据库迁移dmp文件之exp和imp以及expdp和impdp