【问题标题】:Calling Clarion DLL from C#从 C# 调用 Clarion DLL
【发布时间】:2025-12-16 09:35:01
【问题描述】:

我目前在一家 IT 公司工作。他们使用 Clarion 制作软件, 在那个软件中,他们有一个 DLL,可以从他们的数据库中重新计算很多值。我需要从我的 C# 项目中调用这个 DLL。我尝试了一切,但没有成功。

我的代码如下:

public partial class Form1 : Form
{
    [DllImport("EPNORM.dll", EntryPoint = "MyRecalcualate@FlOUcOUcOsbOUc")]
    public static extern void MyRecalcualate(System.Int64 myPtr, System.Int64 myLong, CWByte myByte);

    [DllImport("User32.dll")]
    public static extern Boolean MessageBeep(UInt32 beepType);

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        System.Int64 myPtrTemp = 1234;
        System.Int64 myLongTemp = 5678;
        System.Byte myByteTemp = 88;

        try
        {
            MyRecalcualate(myPtrTemp, myLongTemp, myByteTemp);
            bool messagebeep = MessageBeep(1);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
            MessageBox.Show("Successful");
        }
    }
}

问题是当我用断点调用它时,它只是消失在 MyRecalcualate 方法中,并在 2 秒后到达 finallly 块并重新显示而无需从 DLL 执行任何操作。这是因为我需要修复 DLL 方法中的某些内容还是因为我的调用错误?

下面调用的参数是:MyRecalculate(LONG, LONG, BYTE)

MyRecalcualate      PROCEDURE (MyStringPtr, MyLong, MyByte) ! Declare Procedure
LOC:CString         CSTRING(255)
LOC:Byte            BYTE
CODE
! clear completely LOC:CString with null values
LOC:CString = ALL('<0>', SIZE(LOC:CString))

! load string value, byte by byte, from memory address passed (MyStringPtr) and put into LOC:CString
I# = 0
LOOP
     PEEK(MyStringPtr + I# , LOC:Byte)
     IF LOC:Byte = 0 THEN BREAK END
     LOC:CString[I# + 1] = CHR(LOC:Byte)
     I# += 1
END

MESSAGE('MyString value is:||' & CLIP(LOC:CString))
MESSAGE('MyLong value is:||' & MyLong)
MESSAGE('MyByte value is :||' & MyByte)

这是他们的合同开发人员邮寄给我的参数截图以及他在 VB.NET 中如何调用它: VB.NET 代码:http://imageshack.us/photo/my-images/269/callfromvisualbasictocl.jpg/ CLARION 中的参数:http://imageshack.us/photo/my-images/100/asdxg.jpg/

【问题讨论】:

  • 你能提供更多关于这个 Clarion 库的信息吗?在我看来,您传递的参数有问题。
  • 嘿 dimitris 我用 clarion 侧代码更新了我的帖子
  • 您有任何可以访问这些函数的示例 C/C++ 吗?
  • 您对 Recalculate_Year_Norm 的调用需要 5 个参数,而 MyRecalculate 需要 3 个参数。这是为什么呢?
  • 对不起 dimitris 但我上传了错误的代码,我现在编辑了它(感谢您尝试帮助我,我已经被这个问题困扰了将近一周,现在在网上到处搜索)

标签: c# asp.net dll clarion


【解决方案1】:

第一个参数是一个指向以空字符结尾的字符串的指针。您不能只传递一个随机的 Int64 值。所以你的 pinvoke 应该是这样的:

[DllImport("EPNORM.dll", EntryPoint = "MyRecalcualate@FlOUcOUcOsbOUc")]
public static extern void MyRecalcualate(string myPtr, int myInt, byte myByte);

我相信第二个参数 Clarion LONG 是一个 32 位整数。所以 int 在 C# 方面。更重要的是,您需要仔细检查 Clarion 端的调用约定。你确定它是你的 C# 使用的 stdcall

【讨论】:

  • 嘿,我上传了参数的图片,因为第一个参数是字符串值,但是参数需要像long一样发送。所以他们以某种方式将字符串编码为内存地址并使用类似参数。
  • 我确定您需要按照我在回答中所说的方式进行操作。我的猜测是 Clarion 是 32 位的,LONG 是 32 位整数。这与 32 位指针的大小相同。如果这一切都是真的,那么第二个参数需要在 P/invoke 中输入为 int 而不是 long
  • 正如我刚刚在my most recent question here 中介绍的那样,Clarion LONG 是一个 32 位有符号整数,它映射到 C# System.Int32 (int)。
  • @Dan 谢谢。我更新了。听起来你一直玩得很开心。不敢相信 Clarion 仍然存在。我记得以前用过他们的 TopSpeed Modula-2!!