【问题标题】:Convert a Clarion Procedure Declaration to C# DLLImport将 Clarion 过程声明转换为 C# DLLImport
【发布时间】:2012-10-29 22:08:03
【问题描述】:

如何将此 Clarion 过程声明转换为 C#?它是用 C 语言编写的第 3 方 DLL 的一部分,没有太多文档。我已经列出了 Clarion 中正常工作的方法的原型。在 C# 中,我不确定使用什么类型来替换 *CString。我像@DanielC 建议的那样尝试了char[],但没有奏效。我还发现 Clarion long 是 32 位的(感谢 @shf301)。

号角:

SendRequest Procedure(*CString xData,Long DataLen,Long xTimeout),Byte,Virtual

C#(我试过了,还是不行):

[DllImport("3RD_PARTY_API.dll")]
private static extern long SendRequest(ref string xData, int DataLen, int xTimeout);

当我在 C# 中调用 SendRequest 方法时,我得到了来自 VS2010 的标准 PInvokeStackImbalance was detected 错误。我认为这是参数类型的问题,而不是DllImport declaration 中的CharSetEntryPoint。我真的只是纠结于如何将 *CString 转换为有效的 C# 类型。

【问题讨论】:

    标签: c# pinvoke clarion


    【解决方案1】:

    我找到了答案。我希望我仍然与编写此代码的开发人员一起工作,这样我就可以对他们大喊大叫了。他们在 API 周围放置了一个包装器,这样我列出的带有 3 个参数的方法就可以在没有超时值的情况下调用实际的 API。 PInvokeStackImbalance 异常来自我添加了一个额外参数这一事实。

    这是实际的 Clarion 过程以及正确的 C# 语法:

    号角:

    SendRequest Procedure(*CString xData, Long DataLen), Byte, Virtual
    

    C#:

    [DllImport("NOVA_API.dll", EntryPoint = "SendRequest")]
    private static extern byte SendRequest(string xData, int DataLen);
    

    总之,Clarion *CString 可以在 DLLImport 声明中转换为 .NET string 类型。

    非常感谢那些回复的人。这是我在搜索中使用的另一个资源,我发现它非常有用:pinvoke.net

    【讨论】:

      【解决方案2】:

      在 C# 中,long 始终为 64 位。 Clarion 中的 Long 是 32 位。将 p/Invoke 声明中的 long 参数更改为 int

      【讨论】:

      • 好提示。检查了帮助,你是对的。 LONG: A four-byte signed integer.没有解决问题,但我更近一步......
      【解决方案3】:

      根据维基百科,clarion 可以使用一些奇怪的 TopSpeed “双快速调用”,其中他们使用 4 个 reg 作为参数而不是两个。如果使用此调用约定编译代码,则无法直接从 C# 调用。

      TopSpeed / Clarion / JPI 前四个整数参数在寄存器 eax、ebx、ecx 和 edx 中传递。浮点参数在浮点堆栈上传递——寄存器 st0、st1、st2、st3、st4、st5 和 st6。结构参数总是在堆栈上传递。寄存器用完后,附加参数在堆栈上传递。 eax 中返回整数值,edx 中返回指针,st0 中返回浮点类型。

      如果不是这种情况,那么您的参数之一可能不是正确的大小,否则您将得到一个 AV 而不是损坏的堆栈错误。

      也可以尝试在 dllimport 上设置调用约定。除了 "TOPSPEED" clarion 还支持 stdcall 和 cdecl 但 "TOPSPEED" 是默认设置。下面是与 vb6 和 clarion 进行互操作的教程的链接。

      http://pisoft.ru/verstak/insider/cw_vb.htm

      【讨论】:

      • 我发现 DLL 是用 C 编写的,但我很欣赏这项研究。我会牢记这一点,以备将来之用。我现在在我的问题中澄清了这一点:DLL 是用 C 编写的,Clarion 中的原型可以工作,但 C# 中的 DLLImport 不起作用。
      • 尝试将CallingConvention 上的DllImport 属性设置为CallingConvention.Cdecl
      【解决方案4】:

      你试过char[]吗?我不确定它是否会起作用,但值得一试。 (我会将此作为评论发布,但我没有权利)

      【讨论】:

      • 我试过了,但是没有用。谢谢你的建议。我已经相应地更新了我的问题。
      猜你喜欢
      • 2012-07-22
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 2022-01-18
      • 2013-01-15
      • 2011-04-15
      • 1970-01-01
      • 2011-05-28
      相关资源
      最近更新 更多