用c#调用delphi函数

本文关键字:函数 delphi 调用 | 更新日期: 2023-09-27 18:15:17

我正在从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函数中评估这个条件为真-

if (sCode = nil) or (Length(sCode) <> 21) or (SubscriberID = nil) or (MailshotID = nil) or (LinkID = nil) then
begin
  Result := 'E_INVALIDARG';
end

我只是想知道我是否在传递函数签名的正确数据类型,以及正确的方法是什么。谢谢。

用c#调用delphi函数

您的直接问题可能是您正在将ANSI文本传递给sCode参数。不幸的是,您省略了p/invoke声明,该声明将使这一点变得清楚。

这很容易解决,但你有更大的问题。这个函数很难调用,因为它的设计不正确。只有当它返回由编译器分配的常量字符串而不是堆分配的字符串时,它才是可行的。您可以强制它使用该签名,如果您:

  1. 从本地代码导出一个deallocator函数。
  2. 使用共享堆分配字符串,例如COM堆。

看起来你正在返回字符串形式的COM错误代码。这是反常的。相反,您可以通过返回HRESULT来简化您的工作。

无论如何,要回答这个直接的问题,你像这样声明p/调用:

[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类型的输出参数。这封装了一个COM BSTR。
  • 在托管端声明一个string类型的out形参。用[MarshalAs(UnmanagedType.BStr)]修饰该参数。

请注意,您不能封送WideString返回值给MS工具,因为Delphi使用不同的ABI来返回值。这就是为什么要使用out参数