在C#中调用delphi函数
作者:互联网
我正在从C#的dll中调用一个delphi函数.
这是delphi函数签名-
function CALinkDecode(sCode: PWideChar; SubscriberID, MailshotID, LinkID: PDWORD):
PAnsiChar; stdcall;
这就是我所说的.
string input = "qvoxyetvr7wksss2zbrmr";
int cas, cam, cal;
var errorString = CALinkDecode(input, out cas,
out cam, out cal);
但是当我运行该应用程序时,它在delphi函数中将这种情况评估为true-
if (sCode = nil) or (Length(sCode) <> 21) or (SubscriberID = nil) or (MailshotID = nil) or (LinkID = nil) then
begin
Result := 'E_INVALIDARG';
end
我只想知道我是否为函数签名传递了正确的数据类型,以及正确的方法是什么.谢谢.
解决方法:
您的直接问题很可能是您将ANSI文本传递给sCode参数.不幸的是,您省略了p / invoke声明,这很清楚.
这很容易解决,但是您有更大的问题.该函数的设计不正确,因此很难调用.仅当它返回由编译器分配的常量字符串而不是堆分配的字符串时,它才可行.如果您满足以下条件,则可以强制其使用该签名:
>从本机代码导出解分配器函数.
>使用共享堆分配字符串,例如COM堆.
看起来您正在以字符串形式返回COM错误代码.这是不对的.相反,您可以通过返回HRESULT使生活变得非常轻松.
无论如何,要回答直接问题,您可以这样声明p / invoke:
[DllImport(@"Mylib.dll", CharSet=CharSet.Unicode)]
static extern IntPtr CALinkDecode(
string sCode,
out uint SubscriberID,
out uint MailshotID,
out uint LinkID
);
然后像这样打电话
IntPtr retvalptr = CALinkDecode(...);
然后将指针编组为字符串
string retval = Marshal.PtrToStringAnsi(retvalptr);
但是请记住,这仅在返回的字符串数据是静态分配的情况下才有效.否则,您将发生泄漏或访问冲突.
我的主要建议是重新设计界面.不要在字符串中返回错误代码.
一般而言,如果必须将字符串从Delphi传递到C#,请执行以下操作:
>在Delphi代码中声明WideString类型的out参数.这包装一个COM BSTR.
>在管理端声明一个字符串类型的out参数.用[MarshalAs(UnmanagedType.BStr)]装饰该参数.
请注意,您不能将WideString返回值封送给MS工具,因为Delphi使用其他ABI作为返回值.这就是为什么使用out参数的原因.
标签:c,pinvoke,delphi 来源: https://codeday.me/bug/20191030/1971106.html