在不同 Delphi 版本之间发送 TStringList

Sending TStringList between different Delphi versions

我正在将我的 Delphi 5 源代码迁移到 Delphi 10 柏林。我的项目中有许多导出函数的 DLL。这些函数是从其他 DLL 调用的。有两个我无法迁移到 Delphi10 的 DLL,但我仍然想在我的程序中使用它们。 举个例子:

function DoSomething( aList: TStringList ): Boolean; external 'Delphi5.dll';

我想从我的 Delphi 10 项目中调用 "DoSomething"。但问题是,Delphi 5 中的 TStringList 与 Delphi 10 Berlin (unicode) 中的 TStringList 不兼容。它会起作用,当 DoSomething 有一个像 "aString: AnsiString" 这样的参数时,因为 AnsiString 与 Delphi 中的 "string" 兼容 5.

有没有办法在这两个 Delphi 版本之间发送列表?也许是 TList 或其他东西?当然,我可以发送一个在字符串之间带有分隔符的 AnsiString 来模拟一个列表,但我想要一个干净的解决方案,因为我有很多这样的导出函数。

谢谢!

如果要在 DLL 内部使用对象引用,则永远不要将其从 EXE 传递到 DLL,反之亦然。仅当 DLL 所做的所有操作都是将对象传递回 EXE(反之亦然),例如通过回调函数,才能将对象引用安全地传递给 DLL。

如您所见,如果 EXE 和 DLL 不是使用相同版本的 Delphi 编译的,则对象引用无效。即使它们是用相同的版本编译的,我怀疑某些编译器选项可能会使它们不兼容(想到 {$Align},尽管我从未验证过)。即便如此,仍然可能会出现一些不兼容问题(例如由于 RTTI 不匹配而导致的 "Cannot assign TStringList to TStringList" 错误)。

可以通过对代码进行最少更改来解决问题的方法是更改​​函数声明以将接口传递给 DLL,并围绕 TStringList 创建一个支持该接口的包装器。所述界面需要支持 TStringList.

所需的所有功能
function DoSomething( aList: IStringList ): Boolean

接口可以在 DLL/EXE 之间传递,而不会出现与对象引用相关的大多数问题(只要它们在编译时使用完全相同的接口定义)。 (编辑:您仍然需要确保传递给接口方法的数据可以安全地传递给 to/from DLL。

也就是说,接口应该显式使用 AnsiString 使用以 null 结尾的 PAnsiChar,甚至 WideString(可以安全地发送 to/from DLL - Reference).

function DoSomething( aListText: PAnsiChar ): Boolean

function DoSomething( aListText: WideString ): Boolean

不要使用String,它在Delphi5中是AnsiString但是UnicodeString是Delphi10。并且不要使用AnsiString,因为由于内部结构差异,它在 Delphi 5 和 Delphi 10 之间不兼容。