编程语言
首页 > 编程语言> > 在C#中调用delphi函数

在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