用C#调用Clarion DLL

4

我目前在一家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");
        }
    }
}

问题在于我使用断点调用时,它会在2秒后消失进入MyRecalcualate方法,并在不执行DLL中任何操作的情况下到达finally块并重新显示。这是因为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
你有没有访问这些函数的C/C++示例? - Peter Ritchie
您对Recalculate_Year_Norm的调用需要5个参数,而MyRecalculate只需要3个。为什么会这样? - Dimitris
嘿,彼得,我不这样做是因为我为之工作的公司将他们整个应用程序都制作成了Clarion :S,而真正的重新计算行是500多行代码,所以他们懒得将其重写为存储过程。 - Mrlondon7100
好的,我注意到了几件事情。首先,在您的入口点中,您有一个拼写错误“MyRecalcualate”。其次,在C#中,您的第一个参数字符串指针被传递为Int64。 - Dimitris
显示剩余3条评论
1个回答

2

第一个参数是指向以 null 结尾的字符字符串的指针。您不能只传递随机的 Int64 值。因此,您的 PInvoke 应该像这样:

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

我认为第二个参数,Clarion LONG,是一个32位整数。在C#端使用int。此外,您需要仔细检查Clarion端的调用约定。您确定它是stdcall,这是您的C#使用的约定吗。


嘿,我上传了一个参数的图片,因为第一个参数是一个字符串值,但是参数需要像长整型一样发送。所以他们以某种方式将字符串编码为内存地址,并将其用作参数。 - Mrlondon7100
1
我确定你需要按照我的回答所说的方式去做。我猜想Clarion是32位的,并且LONG是一个32位的整数。这与32位上的指针大小相同。如果这一切都是真的,那么在P/invoke中第二个参数需要被定义为int而不是long - David Heffernan
正如我在我的最新问题中所提到的,Clarion LONG 是一个32位有符号整数,对应于C# System.Int32 (int)。 - DanM7
@Dan 谢谢。我更新了。听起来你玩得很开心。真不敢相信 Clarion 仍然存在。我记得在过去使用他们的 TopSpeed Modula-2! - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接