C# 中的 Pinvoke c++ 函数,可传递 2 个浮点数

本文关键字:可传递 浮点数 函数 中的 Pinvoke c++ | 更新日期: 2023-09-27 18:35:20

我正在使用 C# 中的非托管 c++ dll,它通过 USB 控制 measuremnet 设备。 首先,我想访问 dll 中的函数,该函数将从设备返回测量值,并在文档中定义如下:

BOOL WINAPI LKIF_GetCalcData(OUT LKIF_FLOATVALUE *CalcData1,OUT LKIF_FLOATVALUE *CalcData2);
typedef enum {
    LKIF_FLOATRESULT_VALID, // valid data
    LKIF_FLOATRESULT_RANGEOVER_N, // over range at negative (-) side
    LKIF_FLOATRESULT_WAITING, // comparator result
} LKIF_FLOATRESULT;
typedef struct {
LKIF_FLOATRESULT FloatResult; // valid or invalid data.
    float Value; // measurement value during LKIF_FLOATRESULT_VALID. 
    Any other times will return an invalid value.
} LKIF_FLOATVALUE;

由于这是我第一次使用 dll,我花了相当长的时间搜索如何使用 PInvoke 在 C# 中定义函数,并且我设法让它部分工作。 我能够调用该函数,并且在函数执行时它似乎正确返回 true 或 false 值。 例如,如果设备已打开并准备就绪,则返回 true,如果我关闭设备,则返回 false。 但是,应包含测量值的两个浮点值始终返回零值。

我首先创建了一个包含 PInvoke 的类:

public class Keyence
{
    [DllImport("c:''LkIF.dll")]
    public static extern bool LKIF_GetCalcData(
        [Out] float CalcData1, [Out] float CalcData2);
}

然后通过 getMeasurement 方法调用:

static bool getMeasurement(ref float MeasurementValue1, ref float MeasurementValue2)
{
    float CalcData1 = new float();
    float CalcData2 = new float();
    bool sucess = Keyence.LKIF_GetCalcData(CalcData1,CalcData2);
    if (sucess)
    {
        // all is ok
        MeasurementValue1 = CalcData1;
        MeasurementValue2 = CalcData2;
        return (sucess);
    }
    else
    {
        MessageBox.Show("Unable to get measurment.");
        return (sucess);
    }
}

要测试该方法,请使用带有按钮和文本框的简单表单,单击按钮时,文本框值将更新为两个测量值。

private void button1_Click(object sender, EventArgs e)
{
    float MeasurementValue1 = new float();
    float MeasurementValue2 = new float();
    bool success = getMeasurement(ref MeasurementValue1, ref MeasurementValue2);
    if (success)
    {
        textBox1.Text = MeasurementValue1.ToString() + "," + MeasurementValue2.ToString();
    }      
}

单击按钮后,文本框中的值将更新为 0,0。

我已经看到很多线程涉及调用传入值的非托管函数,该函数返回值的错误并不多。 我有一种感觉,我可能没有正确定义 c# 中的 C++ 函数,但现在我有点不知所措。

C# 中的 Pinvoke c++ 函数,可传递 2 个浮点数

该函数返回的是结构而不是浮点数。必须在 C# 代码中声明该结构。

public enum LKIF_FLOATRESULT
{
    LKIF_FLOATRESULT_VALID, 
    LKIF_FLOATRESULT_RANGEOVER_N, 
    LKIF_FLOATRESULT_WAITING
}
[StructLayout(LayoutKind.Sequential)]
public struct LKIF_FLOATVALUE
{
    public LKIF_FLOATRESULT FloatResult; 
    public float Value; 
}

然后定义 p/invoke 以将该结构作为 out 参数传递给函数。

[DllImport(@"c:'LkIF.dll")]
public static extern bool LKIF_GetCalcData(
    out LKIF_FLOATVALUE CalcData1, 
    out LKIF_FLOATVALUE CalcData2
);

最后,你像这样调用函数:

LKIF_FLOATVALUE CalcData1;
LKIF_FLOATVALUE CalcData2;
bool success = Keyence.LKIF_GetCalcData(out CalcData1, out CalcData2);

尝试以下操作

public enum LKIF_FLOATRESULT {
    LKIF_FLOATRESULT_VALID,
    LKIF_FLOATRESULT_RANGEOVER_N,
    LKIF_FLOATRESULT_WAITING,
}
public struct LKIF_FLOATVALUE {
    public LKIF_FLOATRESULT FloatResult;
    public float Value;
}
public partial class NativeMethods {
    [DllImport("c:''LkIF.dll")]
    public static extern  bool LKIF_GetCalcData(
        out LKIF_FLOATVALUE CalcData1, 
        out LKIF_FLOATVALUE CalcData2) ;
}