我正在用 C++ 创建一个 DLL,它将在 Delphi 7 项目中使用。
这个问题与this one https://codereview.stackexchange.com/questions/43347/produce-an-array-of-strings-from-a-single-string/43398?noredirect=1#43398,我在这里展示两个函数Validate
and GetToken
只是现在它们将在 C++ 和字符串数组中完成GetToken
产品将被送回德尔福。
问题是我不知道如何在 dll 中创建将返回 c++ 中的字符串数组的函数,并且我不知道如何存储它以供在 Delphi 中进一步使用。
函数的声明如下:
function GetToken(Chain:string):Arrayofstring;
根据您的代码审查,Delphi 代码期望该函数具有以下签名:
function GetToken(Chain: AnsiString): array of AnsiString;
你不能用 C++ 编写这样的函数。 C++ 不知道 Delphi 字符串是什么,也不知道 Delphi 动态数组是什么。这两种类型都需要从 Delphi 的内存管理器分配,而您的 C++ DLL 无法访问该内存管理器。此外,C++不知道如何使用Delphi的register
调用约定。
DLL接口设计得很糟糕。 DLL 永远不应该使用特定于语言的类型,除非它是设计者的意图排除所有其他语言。 (在这种情况下,甚至同一语言的更高版本也被排除在外,因为AnsiString
Delphi 2009 中进行了更改,以包含更多 Delphi 7 无法正确处理的元数据。)选择的最安全的调用约定通常是stdcall
。 Windows API 中的所有内容都使用它。
更好的接口将使用所有语言通用的类型,并且它将规定使用可普遍访问的内存管理。有几种常见的方法可以做到这一点。例如:
-
字符串作为简单的以 null 结尾的字符数组返回 -PAnsiChar
在德尔福;char*
在C++中。 DLL 为字符串分配缓冲区,并为这些字符串的数组分配缓冲区。当主机应用程序完成使用数组和字符串时,它调用 DLL 导出的另一个函数,其中 DLL 释放它分配的内存。例如,这是使用的模型,FormatMessage http://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx;当主机程序完成消息字符串时,它调用LocalFree
.
type
PStringArray = ^TStringArray;
TStringArray = array[0..Pred(MaxInt) div SizeOf(PAnsiChar)] of PAnsiChar;
function GetToken(Char: PAnsiChar): PStringArray; stdcall;
procedure FreeStringArray(StringArray: PStringArray); stdcall;
char** __stdcall GetToken(char const* Chain);
void __stdcall FreeStringArray(char** StringArray);
使用 COM 返回 BStr 对象的安全数组。它与之前的技术类似,但内存管理是由 COM 而不是由 DLL 定义的,因此需要由接口双方定义的内容较少。
-
将回调函数传递给 DLL,因此 DLL 只针对它标识的每个字符串调用该函数一次,而不是返回字符串数组。然后,您不必定义任何数组的样子,并且每个字符串的生命周期可以只是回调调用的生命周期 - 如果主机应用程序想要一个副本,它可以这样做。新的函数签名看起来像这样:
type
TTokenCallback = procedure(Token: PAnsiChar); stdcall;
procedure GetToken(Chain: PAnsiChar; ProcessToken: TTokenCallback); stdcall;
typedef void (__stdcall* TokenCallback)(char const* Token);
void __stdcall GetToken(char const* Chain, TokenCallback ProcessToken);
如果您不是设计 DLL 接口的人,那么您需要向设计者求助并对其进行更改,以便非 Delphi 代码更容易访问。如果您做不到这一点,那么最后的替代方案是在 Delphi 中编写一个 DLL,将您的 DLL 包装起来,以将参数调整为双方都能理解的内容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)