编写dll时的内存分配策略

 

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

完全可以!

一般的策略如下:

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

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

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

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

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

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

 

 

 

在这里需要强调几点:

//1.不用共用内存管理器的话,数据类型需要使用Windows标准类型,如PChar!另外在dll中返回结构体时,最好结构体内的成员为基本数据类型,不要成员又是指针,一不小心就会出错!

//2.PChar是一个指针,一般在主调函数中申请空间时先申请255,并把地址传入dll,dll进行逻辑处理,处理完毕后进行返回,返回时,长度可能远远小于255,所以在返回时通过一个变参告诉主调,实际只用了N个长度,这时主调在主动清理实际使用的长度!

//3.一般在程序中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:=255;

  DllHnd := LoadLibrary(PChar('project1.dll'));

  try

    if (DllHnd <> 0) 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) * 234 (*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;
View Code

 

你可能感兴趣的:(内存分配)