将Delphi const字符串参数传递到内存管理器边界是否安全?

时间:2010-07-05 10:47:50

标签: delphi string const parameters

SUBJ。我想使用字符串而不是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并复制指针,就是这样。我想让Delphi复制数据。将参数声明为“const”会使其安全吗?如果没有,有办法吗?将参数声明为PChar似乎不是一个解决方案,因为你需要每次都抛出它:

procedure SomeExternalProc(s: Pchar); forward;
procedure LocalProc;
var local_s: string;
begin
  SomeExternalProc(local_s); //<<--- incompatible types: 'string' and 'PAnsiChar'
end;

4 个答案:

答案 0 :(得分:13)

这可能会有效,只要您只使用在相同版本的Delphi中编译的代码中的DLL。已知字符串的内部格式会在不同版本之间发生变化,并且您无法保证它不会再次更改。

如果您想避免在任何地方使用它,请尝试包装该功能,如下所示:

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

然后在您的代码中,您拨打MyExternalProc而不是SomeExternalProc,并且每个人都很高兴。

答案 1 :(得分:6)

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

如果一方用不同的语言编写,除了使用PChar或WideString之外别无其他方式(WideStrings由COM内存管理器管理)。

或者您可以编写包装函数:

procedure MyExternalProc(const s: string);
begin
  SomeExternalProc(PChar(s));
end;

答案 2 :(得分:0)

只是添加一个事实:

Delphi允许您简单地将PChar分配给字符串,因此在DLL端您不需要任何类型转换:

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;

这也适用于将PChar作为参数传递给期望(按值)字符串的函数。

答案 3 :(得分:-1)

我建议使用替代内存管理器,例如RecyclerMM或FastMM。它们不需要任何外部共享MM dll,并允许您安全地将字符串传递给dll。作为奖励,您可以在整个应用程序中获得良好的性能提升。

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