【问题标题】:Delphi method signature conversion to c#Delphi方法签名转换为c#
【发布时间】:2011-05-23 17:27:04
【问题描述】:

我在调用的 delphi 2007 函数中有这个签名(SomeOtherFile 是另一个它调用的 DLL):

function MyFunction(Place, Name: PChar):_Recordset; stdcall; far; external 'SomeOtherFile.DLL';

我正在尝试从 C# 代码中调用它,如下所示:

[DllImport("MyFile.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi, EntryPoint="MyFunction")]

public static extern DataSet MyFunction(string Place, [MarshalAs(UnmanagedType.LPStr)]string Name);

每当我运行它并将其存储到变量中时,我都会收到有关类型不匹配的运行时错误。我想我读错了签名,但我不知道它应该是什么。

编辑 实际错误是:调用 PInvoke 函数 [...] 使堆栈不平衡...我也尝试使用 MarshalAs 属性的两个参数,但它抛出了同样的事情。

【问题讨论】:

  • “类型不匹配”通常是编译时错误,而不是运行时错误。你能引用错误文本并告诉我们你得到的错误的类名吗?另外,是什么让您认为第二个参数需要特别编组,而第一个参数不需要? MyFunction 对这些指针有什么作用? (它是写入缓冲区,还是只读取缓冲区?)最后,DataSet_Recordset 是什么?
  • 很难看到 P/Invoke 编组器匹配 _RecordsetDataSet!您也不需要MarshalAs 属性,但这是一个细微差别。
  • @Dan 为什么你在Name 参数中使用MarshalAs 而不是Place,如果两个参数类型相同?
  • @RRUZ 但您也不需要它,因为它是字符串参数的默认编组。此外,同一类型的两个参数可能需要不同的编组:考虑一个 IN PChar 参数和一个 OUT PChar 参数。
  • @David 但在这种情况下,函数被声明为 function MyFunction(Place, Name: PChar) 而不是 function MyFunction(Place, var Name: PChar) 所以我想知道如果两个参数都相等,为什么 OP 使用 MarshalAs

标签: c# delphi delphi-2007


【解决方案1】:

我已经进行了一些挖掘,我认为您需要将返回值编组为Recordset 接口。我确信 P/Invoke marshaller 不会神奇地将您的 Delphi _Recordset 转换为 .net DataSet 类实例。

所以我认为你可以这样写:

[DllImport("MyFile.dll")]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object MyFunction(string Place, string Name);

这样称呼

Recordset rs = (Recordset) MyFunction(Place, Name);

我假设PlaceName 参数是输入参数,在这种情况下,字符串的默认编组就可以了。

您不需要指定 ANSI 字符集,因为这也是默认值。如果入口点与 C# 函数同名,则无需命名入口点。您无需指定调用约定,因为 stdcall 是默认值。

Recordset 接口位于 ADODB 命名空间中。

顺便说一句,在 Delphi 函数导入中使用 far 是虚假的。一旦我们离开了 16 位世界,far 关键字就不再起作用了。

【讨论】:

  • 感谢 David 的帮助(还有 RRUZ),但我遇到了同样的错误。如果有帮助,以下是有人在 Delphi 中编写代码的方式: Recordset := MyFunction('Home',PChar('Steve'));第二个参数让我觉得我的签名是错误的。
  • 函数的参数就可以了。我相信 P/Invoke 的一部分是好的。问题肯定是 RecordSet。我有另一个想法。请多多包涵。
  • @Dan 我已经编辑了函数以具体说明返回值的编组。但是,如果这会改变任何东西,我会感到惊讶,因为默认编组器肯定可以解决如何编组接口指针。顺便说一句,您是否 100% 确定该函数正在使用 stdcall?当您混合使用 cdecl 和 stdcall 时,也经常发生不平衡的堆栈。为什么你使用 C# 中的 cdecl 会发生什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多