C++ 在Delphi中实现C-DLL

C++ 在Delphi中实现C-DLL,c++,delphi,dll,C++,Delphi,Dll,我正在努力从C dll实现一个函数。它被宣布为 int DetectTransactionCode(wchar_t* wi_type, wchar_t* wi_id); 如果在我的delphi代码中声明并调用它 function DetectTransactionCode (var wi_type, wi_id: PWideChar): Integer; cdecl; external 'WiGroupDetect.dll'; procedure TForm20.Button2Cl

我正在努力从C dll实现一个函数。它被宣布为

int DetectTransactionCode(wchar_t* wi_type, wchar_t* wi_id);
如果在我的delphi代码中声明并调用它

function DetectTransactionCode (var wi_type, wi_id: PWideChar): Integer;
     cdecl; external 'WiGroupDetect.dll';

procedure TForm20.Button2Click(Sender: TObject);
var witype,wi_id : widestring;
res : integer;
begin
 res := DetectTransactionCode(PWideChar(witype),PWideChar(wi_id));
 showmessage(res.tostring);
 ShowMessage(witype +' & ' +wi_id);
end;
我收到结果,但是我的witype和WIU id导致访问冲突

我也尝试过:

Function  DetectTransactionCode (var witype,wi_id :widestring ) : Integer cdecl;
                  external 'WiGroupDetect.dll';

procedure TForm20.Button2Click(Sender: TObject);
var witype,wi_id : widestring;
 res : integer;
begin
 res := DetectTransactionCode(witype,wi_id);
 showmessage(res.tostring);
 ShowMessage(witype +' & ' +wi_id);
end;
我假设这两个参数都是out参数。第三方提供了以下内容:

成功返回1,取消/失败返回0

注意:阻塞调用仅在以下情况下返回: 1-检测到wiCode, 2-调用KillDetectionProcess(), 3–发生错误或故障,或 4-最终超时(30分钟)过期

参数: wi_type在成功时返回检索到的令牌类型(即QR为“WIQR”);或取消/失败时为“无”。 wi_id返回成功检测到的wiCode;取消时“取消”;或带有关于故障的附加错误信息(即“错误:…”)

我已经尝试过将参数更改为ansistring、unicodestring,但仍然遇到同样的问题。我怀疑它与var参数有关,但不确定如何克服它。任何协助都将不胜感激

他们给了我一个C示例实现

[DllImport("WiGroupDetect.dll", EntryPoint = "DetectTransactionCode", CallingConvention =             CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern int DetectTransactionCode([MarshalAsAttribute(UnmanagedType.LPWStr)]  StringBuilder strWITYPE, [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder strUID);

不确定这是否会改变我的Delphi实现

这两个参数的类型为
wchar\u t*
,它是指向16位字符的指针。通常这意味着指向以null结尾的宽UTF-16字符数组的指针

因此,代码的正确翻译如下:

function DetectTransactionCode (wi_type, wi_id: PWideChar): Integer;
    cdecl; external 'WiGroupDetect.dll';
您使用了
var
类型的
WideString
参数。这将匹配作为指向
BSTR
的指针的参数,这是完全不同的

我假设使用
cdecl
调用约定,这是我遇到的每个C编译器的默认值。如果您有一些额外的信息表明该函数是stdcall,那就这样吧。但如问题中所述,这是
cdecl


目前还不清楚数据是如何流动的。这两个字符串参数是输入还是输出?一个进来一个出去吗?如果其中一个是out参数,那么您需要某种方法来知道要分配多大的缓冲区。函数不允许传递缓冲区长度这一事实表明数据流入。也就是说,在这种情况下,参数应该是C代码中的
const wchar\u t*
。这里有很多不确定性。请注意,函数原型并没有完全定义函数的语义

谢谢大卫的回答,他们帮了你的忙。我用这个代码成功了。我知道,如果传递回的字符串比我提供的长度长,那么将出现错误

function DetectTransactionCode (wi_type, wi_id: pwidechar): Integer;
stdcall; external 'WiGroupDetect.dll';

procedure TForm20.Button2Click(Sender: TObject);
var witype,wi_id :  widestring;
 res : integer;
begin
 setlength(witype,10);
 setlength(wi_id,100);
 res := DetectTransactionCode(pwidechar(witype),pwidechar(wi_id));
 showmessage(res.tostring);
 setlength(witype,pos(#0,witype)-1);
 setlength(wi_id,pos(#0,wi_id)-1);
 ShowMessage(trim(witype) +' & ' +trim(wi_id));
end;

C/C++中的默认调用约定是
cdecl
。感谢您的快速响应。我已经从第三方添加了一些额外的细节。我假设这两个参数都是基于它们的信息的out参数,但我不确定这将如何更改Delphi函数声明。参数语义不会更改声明,而是更改调用函数的方式。如果数据流出,则需要分配由函数填充的字符数组。这些数组必须有多长?我们无法回答此问题。您应该停止使用
WideString
。这是用于COM互操作的。使用
字符串
,它是
解压的别名
。就我个人而言,我会为函数调用使用固定长度的数组,然后将它们分配给字符串变量。因此,避免调用
SetLength
Pos
将是更好的选择。如果需要,可以直接将它们分配给字符串。奥利弗可以使用
SetLength(witype,Pos(#0,witype)-1)
,而不是
SetLength(witype,StrLen(witype))
,或者更好的是,
s:=witype。如果
witype
是字符的
数组[…],那么甚至可以在
Trim()
中直接使用它。所需的转换将隐式完成。谢谢,我已将函数更改为使用WideChar的数组[0..100],并使用字符串而不是widestring。非常感谢你的帮助。