最近再写 dll   为了通用性(c#可以调用)  输出函数肯定用pchar 作为参数 和 返回值了 这是毫无疑问的 查阅了些资料 
http://blog.sina.com.cn/s/blog_4ff1251f0100dsu6.html
并且在其他地方下到一些代码 function StrPch(const stPas: string): PChar;
// Pascal -> PChar
// 直接使用 PChar 转化有时会转化出错
begin
  GetMem(Result, Length(stPas) + 1);
  StrPCopy(Result, stPas);
end;function GetSpellCode(szText: PChar; iMode, iCount: Integer): PChar;
// Call MakeSpellCode
begin
  Result := StrPch(MakeSpellCode(String(szText), iMode, iCount));  //这里直接用pchar 有时会报错? 搞不懂
end;function GetAdminPath: ShortString; stdcall;
var
  vPath: pchar
  vSize: Integer;
begin  vSize := MAX_PATH;
  vPath := GetMemory(vSize);
  ExpandEnvironmentStrings('%HOMEDRIVE%%HOMEPATH%', vPath, MAX_PATH);
  //ShowMessage(StrPas(vPath));
  Result := StrPas(vPath);  end;
都用到了  内存分配函数 可没有释放  势必会造成内存泄露吧(CheckMem.pas检查有)
请问 dll  涉及输出函数中 string 标准写法 如何?

解决方案 »

  1.   

    问题1 : 再dll中分配内存还是exe中问题2  : 再dll中分配内存会自动释放吗
    问题3  :dll 返回 pchar 会有不稳定的情况 ? 
      

  2.   

    我在DLL中这样用还没出现过问题//********取得当前可执行文件名
    procedure GetApplicationName(var Lp:String);StdCall;
    begin
      StrCopy(PChar(Lp),PChar(ChangeFileExt(ExtractFileName(Application.ExeName),'')));
    end;
      

  3.   


    对于文件名 不可能超过  255 吧 所以你的没有问题 也可直接使用 shortstring
      

  4.   

    GetMem没有FreeMem肯定就是泄漏
    dll要给其他语言用,尽量只是用PAnsiChar吧。string毕竟是delphi自己的东西
      

  5.   

    LZ,对于String的全部用PChar代替,在调用之前申请内存空间,然后传入参数就行。
      

  6.   

    function StrPch(const stPas: string): PChar;
    // Pascal -> PChar
    // 直接使用 PChar 转化有时会转化出错
    begin
      GetMem(Result, Length(stPas) + 1);
      StrPCopy(Result, stPas);
    end;
    这个写成下面的样子就应该没有问题了
    function StrPch(const stPas: string): PChar;
    // Pascal -> PChar
    // 直接使用 PChar 转化有时会转化出错
    begin
      GetMem(Result, Length(stPas) + 1);
      //StrPCopy(Result, stPas);
      CopyMemory(Result, stPas[1], Length(stPas));
      Result[Length(stPas)] := #0;
    end;
      

  7.   

    function GetSpellCode(szText: PChar; iMode, iCount: Integer): PChar;
    // Call MakeSpellCode
    begin
      Result := StrPch(MakeSpellCode(String(szText), iMode, iCount));  //这里直接用pchar 有时会报错? 搞不懂
    end;
    //试一试下面的方式?
    function GetSpellCode(szText: PChar; iMode, iCount: Integer): PChar;
    // Call MakeSpellCode
    begin
      Result := StrPch(MakeSpellCode(PChar(szText), iMode, iCount));  
    end;
    //试
      

  8.   

    继续讨论 
    如果 dll 函数 返回值为pchar  exe 里再访问该地址 大量访问会不会有异常 ?
    就像上面提到的  直接 pchar('sss')  返回有事会出错。
      

  9.   

    因为在这里 有前辈总结 dll经验“ 对不使用var前缀要回传的参数请使用内存拷贝类函数,如StrPCopy,CopyMemory,Move等。  原因:dll和主应用程序并不能很好的共用一块内存,所以必须进行内存拷贝才能正确将dll  中的内容回传(拷贝)到主应用程序中。也因此对回传的地址标识类参数,在调用dll之前必须  进行内存分配,例如Delphi中:AllocMem(n integer),Pb中:Space(n long)。”
    http://blog.sina.com.cn/s/blog_4ff1251f0100dsu6.html
      

  10.   

    这里的问题是  如果在 exe 中 分配内存 getmem  freemem  采用 windows api 方式传递参数 
    如 :function   GetSysParamEx(ParamKey:PChar;   const   myResult:   pchar):boolean;stdcall;
    那么 当不知道 myResult 大小时  怎么分配内存 
      

  11.   

    是否会出错,跟访问量没有关系。pchar('sss')还是用到了String!为了避免一些不可避免的问题,不要在Dll与Exe中传递String了,折腾。都是BorlandMM搞的鬼。
      

  12.   

    经过测试 可以搞定了  pchar 内存分配可以再exe 也可以再 dll内进行 只不过dll里需要额外增加一个 释放内存函数 
    这里推荐 exe  管理内存 dll只负责 填充pchardll 内要使用 strcopy move等内存复制函数 而不要简单返回一个指针。