Delphi 如何将字符串数组传递到外部DLL?

Delphi 如何将字符串数组传递到外部DLL?,delphi,Delphi,我有这样一个外部函数: extern "C" __declspec(dllexport) int __cdecl Identify(BSTR* bstrTemplates, __int64 lCount, __int64* lIndex, __int64* lRetCode) bstrTemplates应该是字符串数组 我的函数在D7中应该是什么样子,以及如何将字符串数组传递给外部函数。现在我没法动脑。BSTR*是指向BSTR的指针(在Delphi中,BSTR是一个宽字符串) 编辑:要使答案

我有这样一个外部函数:

extern "C" __declspec(dllexport) int __cdecl Identify(BSTR* bstrTemplates, __int64 lCount, __int64* lIndex, __int64* lRetCode) 
bstrTemplates应该是字符串数组


我的函数在D7中应该是什么样子,以及如何将字符串数组传递给外部函数。现在我没法动脑。

BSTR*是指向BSTR的指针(在Delphi中,BSTR是一个宽字符串)

编辑:要使答案完整(并使罗布·肯尼迪高兴:-)):

大多数直译:

function Identify(bstrTemplates: PWideString; lCount: int64; lIndex: PInt64; lRetCode: PInt64): Integer; cdecl external 'mydll.dll';
或更多德尔福方式:

function Identify(bstrTemplates: PWideString; lCount: int64; var lIndex: Int64; var lRetCode: Int64): Integer; cdecl external 'mydll.dll';
甚至(但这取决于bstrTemplates是否可以为零):


在传递bstrTemplates时使用数组中的第一个元素(例如@MyArray[0])

在Delphi中,BSTR是一个宽字符串,而在Delphi中,指向BSTR的指针也是指向宽字符串的指针,但就C代码而言,它很可能是一个数组引用。处理此类数组的一种典型方法是使用以null结尾的数组,我假设这里就是这样做的

因此,我们需要在Delphi中声明一个WideString数组,并将最后一个元素保留为null,或者在Delphi中保留为
nil

var
  templates : array of WideString;
begin
  SetLength(templates, 3); // 2 template names + 1 nil
  templates[0] := 'template1';
  templates[1] := 'template2';
  templates[2] := nil;

  Identify(@templates[0], ....); // pass it as a pointer to the first element

我不能保证这会奏效。我在这里猜测,而且还没有尝试过(这将涉及到创建一个C项目和测试),所以这可能会失败得很惨。不过值得一试。

终于解决了这个问题。这是动态数组。看起来它不能用作C样式数组。看起来长度前缀混淆了c dll。此处的记录包括原型和用途:

类型

声明

function Identify(var ATemplates: TArrayOfWideString; ATemplatesCount: int64; var ATemplateIndex: int64; var ARetCode: int64): Integer; cdecl; external 'Identify.dll';
用法


你的答案有点令人困惑。BSTR在Delphi中是一个广泛的字符串。指向BSTR的指针与宽字符串不同。我想这就是你想说的,但它不是这样读的,至少对我来说不是这样。这里的“Which”指的是“正在讨论的事情”,即“指向BSTR的指针”。指向BSTR的指针基本上与指向序列中第一个BSTR的指针相同。我猜数组是以null结尾的。@Lasse:是的,我想说BSTR是Delphi中的一个宽字符串(我对文本做了一点修改,以澄清这一点,谢谢)其余的参数似乎不是问题的一部分。是的,对于动态数组,始终传递指向第一个元素的指针,并且由于对于静态数组也可以这样做,因此将数组传递给c(++)dll的(+1)Ok是一种安全的做法。乍一看是有道理的。但有两个怪癖。将nil分配给模板[2]不起作用。编译器告诉我WideString和指针是不兼容的类型。因此,如果我将数组传递给函数,则将length设置为3并保持模板[2]不变会导致访问冲突。您不能将nil分配给宽字符串(但可以分配空字符串“”),但我认为lCount参数可能指示数组中的元素数?所以在这个例子中,你也做了SetLength(..,2)。如果你得到了一个访问冲突,那么你还做了一些错误的事情。仅此代码不会崩溃。如果用户崩溃,可能是因为他们为Identify()编写的外部导入代码不正确。同样的问题:确实如此。这是我在一个德国论坛上的问题。
type
  TArrayOfWideString= array[0..999] of WideString;
function Identify(var ATemplates: TArrayOfWideString; ATemplatesCount: int64; var ATemplateIndex: int64; var ARetCode: int64): Integer; cdecl; external 'Identify.dll';
var
  templateIndex, retCode: int64;
  templates: TArrayOfWideString;
  retval: integer;

//TODO: range checking for TArrayOfWideString needed

templates[0] := 'template1';
templates[1] := 'template2';

retVal := Identify(templates, 2, scanIndex, retCode);