简体   繁体   English

在C#中Pinvoke C ++函数传出2个浮点数

[英]Pinvoke c++ function in c# that passes out 2 floats

I'm working with an unmanaged c++ dll in C# that controls a measuremnet device over USB. 我正在使用C#中的非托管c ++ dll,该dll通过USB控制measuremnet设备。 To start I would like to access the function within the dll that will return the measurment values from the device and is defined in the documentation like this: 首先,我想访问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;

As this is the first time I've worked with a dll I spent quite awhile searching how to use PInvoke to define the function in C# and I've managed to get it partially working. 因为这是我第一次使用dll,所以花了相当长的时间搜索如何使用PInvoke在C#中定义函数,并且设法使它部分起作用。 I'm able to call the function and it appears return a value of true or false correctly when the function executes. 我能够调用该函数,并且该函数执行时它似乎正确返回了true或false的值。 For example if the device is on and ready it returns true and if I shut the device off it returns false. 例如,如果设备已打开并准备就绪,则返回true;如果我关闭设备,则返回false。 However, the two float values that should contain the measurement value always return a value of zero. 但是,应包含测量值的两个浮点值始终返回零值。

I started by creating a class that contains the PInvoke: 我首先创建一个包含PInvoke的类:

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

This then called by a getMeasurement method: 然后通过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);
    }
}

To test the method have a simple form with a button and a text box and when the button is click the text box value is updated with the two measurement values. 要测试该方法,可以使用带有按钮和文本框的简单表单,单击按钮时,将使用两个测量值更新文本框值。

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();
    }      
}

After clicking the button the value in the textbox updates to 0,0. 单击按钮后,文本框中的值将更新为0,0。

I've seen plenty of threads that involve calling an unmanaged function where a value is passed in, bugt not very many were the function returns a value. 我已经看到很多线程都涉及到调​​用传递值的非托管函数,但并不是很多该函数返回值。 I have a feeling I may not be correctly defining the C++ function in c#, but I'm at a bit of a loss now. 我觉得我可能没有在c#中正确定义C ++函数,但是现在有点茫然了。

The function is returning a struct rather than a float. 该函数返回的是结构而不是浮点数。 You have to declare that struct in your C# code. 您必须在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; 
}

And then you define your p/invoke to pass that struct to the function, as an out parameter. 然后定义p / invoke,以将该结构作为out参数传递给函数。

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

And, finally, you call the function like this: 最后,您可以像下面这样调用该函数:

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

Try the following 尝试以下

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) ;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM