使用来自动态链接库(DLL)的接口是否安全?

4
当我想在DLL中导出一个类时,将其从接口派生并通过导出函数返回该接口是否是正确的方法?
//exported dll function, which is used in the exe.
function MyClass_Create: IMyClass;
begin
  result := TMyClass.Create;
end;

关于内存管理呢?我是否可以随意传递不同的接口和字符串而不必担心崩溃问题?

IMyClass = interface
  procedure SetString(aMsg: string);
  function GetString: string;

  procedure SetClass(aClass: ITestClass);
  function GetClass: ITestClass;
end;
2个回答

5

接口引用与内存管理无关。通常你会从DLL导出一个返回接口引用的函数,而不需要关心内存管理。使用引用计数接口,你可以确保实现接口的对象实例也在DLL中被释放。

字符串则不同。无论你是导出接口还是导出扁平函数,都适用相同的限制。

顺便说一下,你的问题标题是不正确的,在Delphi中不存在“接口实例”。


在使用接口的循环引用时(即,实现类引用共享接口),请注意潜在的内存泄漏问题 - 在这种情况下,Delphi缺乏垃圾收集器或“零弱指针”功能。请参见http://blog.synopse.info/post/2011/12/08/Avoiding-Garbage-Collector%3A-Delphi-and-Apple-on-the-same-side。 - Arnaud Bouchez
循环引用是参考计数的常见问题。肮脏技巧Pointer(IntRef):= nil可以帮助设置接口引用为空,而不改变引用计数。 - kludg

3
使用这种接口将确保实现接口的对象将在同一堆上创建和释放。
然而,这并不能解决动态字符串类型在不同堆上分配和释放的问题。有很多可能的解决方案,但在我看来,最好的方法是跨模块边界使用WideString。
WideString类型是COM BSTR的包装器,分配在共享的COM堆上。您只需要为接口使用WideString。实现类的内部可以使用本地的Delphi字符串。
与字符串一样,动态数组也存在问题。尝试在模块之间传递动态数组是不安全的。没有类似于WideString那样方便的解决方案。您可以使用变量数组,但与WideString相比,这相当笨拙。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接