2012-05-23 46 views
2

我正在使用C#中的非託管C++ dll,通過USB控制measuremnet設備。要開始我想訪問DLL中的函數將從設備返回measurment值和這樣的文檔中定義:C++中的Pinvoke C++函數傳出2個浮點數

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++函數,但現在我有點不知所措了。

回答

0

嘗試使用以下

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

} 
+0

多虧了兩個答案。添加枚舉和結構定義解決了問題。我確實需要將每個定義爲公開的,以便讓它工作。 – user1413606

+0

@用戶請記得接受最有幫助的答案 –

4

該函數返回一個結構,而不是一個浮子。您必須在您的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);