在不同 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 之间不兼容。
我正在将我的 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 之间不兼容。