2014-03-05 19 views
0

我試圖訪問和修改的結構是在一個DLL元素C DLL的結構和訪問數組。我按照關於如何使用struct從DLL這個例子:http://nawatt.com/index.php/corporate/blog/78-using-c-dlls-in-c從C#

我已經成功地更改爲非數組變量,但每當我試圖更改到一個數組我得到一個運行時錯誤。

這是我的C DLL的代碼示例:

//lib_qrs.dll 

    #ifdef __cplusplus 
    extern "C" { 
    #endif  

    typedef struct TEST_STRUCT 
    { 
     unsigned short check[5]; 

    } test_struct; 

    __declspec(dllexport) void __stdcall test(test_struct *test, unsigned short val){ 

      // This is an example of what DOES NOT WORK 
      test->check[0]=val+1; 
      test->check[1]=val+2; 
      test->check[2]=val+3; 
      test->check[3]=val+4; 
      test->check[4]=val+5; 
    } 
    #ifdef __cplusplus 
    } 
    #endif 

這是我的C#代碼的例子:

[StructLayout(LayoutKind.Sequential)] 
    public struct TEST_STRUCT 
    { 
     public UInt16[] check; 

    } 

    public class Program 
    { 
     [DllImport("lib_qrs.dll", EntryPoint="test", CallingConvention = CallingConvention.StdCall)] 
     public static extern void test(ref TEST_STRUCT test, int val); 
     public TEST_STRUCT testStruct = new TEST_STRUCT(); 

     static void Main(string[] args) 
     { 
      testStruct.check=new UInt16[5]; 
      // WHERE ERROR OCCURS 
      test(ref testStruct, 5); 
     } 
    } 

,我得到的錯誤是: *「未處理的異常型的「System.AccessViolationException」發生在將Test.exe 額外的資料:嘗試讀取或寫入受保護的存儲器這往往是一個指示其他內存已損壞「。

我明白,我有我的時候我複製結構在C#中非常小心內存分配,但我不知道我做錯了或者我該如何解決這個問題陣。 有沒有人有我如何解決這個問題的想法?

回答

3

該陣列的默認編組是unsigned short*,不unsigned short[]。你需要應用[MarshalAs]屬性來告訴pinvoke編組。修復:

[StructLayout(LayoutKind.Sequential)] 
    public struct TEST_STRUCT { 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
     public UInt16[] check; 
    } 

而且因爲你是在陣列中返回值,你也必須告訴PInvoke的編組,它需要數組值複製回來。這需要[OUT]屬性:

[DllImport("lib_qrs.dll")] 
    public static extern void test([Out] ref TEST_STRUCT test, int val); 

請注意,無論是不必要的,如果你只需要聲明的說法與ushort [],假設結構不包含任何附加字段。

+0

謝謝,這真是棒極了。唯一的區別是,如果我用[OUT]屬性我得到了告訴我生成錯誤我要麼需要使用ref或[OUT]。所以當我把它作爲參考時,它就起作用了。 – gtdevel