代码之家  ›  专栏  ›  技术社区  ›  himself

跨内存管理器边界传递Delphi const string参数安全吗?

  •  7
  • himself  · 技术社区  · 14 年前

    主题。我想使用字符串而不是PChar,因为这节省了我很多铸造,但如果我只是这样做

    procedure SomeExternalProc(s: string); external SOMEDLL_DLL;
    

    然后用非共享内存管理器在其他项目中实现:

    library SeparateDll;
    procedure SomeExternalProc(s: string);
    begin
      //a bla bla bla
      //code here code here
    end;
    

    我(正式地)不保证Delphi不会因为任何原因决定改变字符串,修改它的引用计数器,复制或唯一它,或者其他任何事情。例如

    var InternalString: string;
    
    procedure SomeExternalProc(s: string);
    begin
      InternalString := s;
    end;
    

    Delphi增加refcounter并复制一个指针,就是这样。我想把数据复制一下。将参数声明为“const”是否因此而安全?如果没有,有办法吗?将参数声明为PChar似乎不是一个解决方案,因为每次都需要强制转换它:

    procedure SomeExternalProc(s: Pchar); forward;
    procedure LocalProc;
    var local_s: string;
    begin
      SomeExternalProc(local_s); //<<--- incompatible types: 'string' and 'PAnsiChar'
    end;
    
    4 回复  |  直到 14 年前
        1
  •  13
  •   Mason Wheeler    14 年前

    只要您只使用在同一版本Delphi中编译的代码中的DLL,那么这可能是可行的。的内部格式 一串 已经知道在不同版本之间会发生更改,并且您无法正式保证它不会再次更改。

    如果您想避免在任何地方使用强制转换,请尝试包装函数,如下所示:

    procedure SomeExternalProc(s: Pchar); external dllname;
    procedure MyExternalProc(s: string); inline;
    begin
      SomeExternalProc(PChar(local_s));
    end;
    

    然后在你的代码中,你调用 MyExternalProc 而不是 SomeExternalProc ,大家都很开心。

        2
  •  6
  •   Community Niall    7 年前

    如果应用程序和DLL都是在同一个Delphi版本中编写的,只需使用共享内存管理器(更多详细信息) here

    如果其中一方是用不同的语言编写的,那么除了使用PChar或WideString(WideString由COM内存管理器管理)没有其他方法。

    也可以编写包装函数:

    procedure MyExternalProc(const s: string);
    begin
      SomeExternalProc(PChar(s));
    end;
    
        3
  •  0
  •   dummzeuch Stijn Sanders    14 年前

    再加上一个事实:

    function MyDllFunction(_s: PChar): integer;
    var
      s: string;
    begin
      s := _s; // implicit conversion to string
    
      // now work with s instead of the _s parameter
    end;
    

        4
  •  -1
  •   Andrew    14 年前

    在Delphi2006及更高版本中,FastMM用作默认内存管理器。它也是搜索内存泄漏的好工具。