从C#访问C DLL结构中的数组

时间:2014-03-05 16:41:10

标签: c# c arrays dll struct

我正在尝试访问并更改DLL中的结构中的元素。我已经按照这个示例介绍了如何使用DLL中的structhttp://nawatt.com/index.php/corporate/blog/78-using-c-dlls-in-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);
        }
     }

我得到的错误是: *“Test.exe中发生了'System.AccessViolationException'类型的未处理异常 附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。“

我理解当我在C#中复制我的结构时,我必须非常小心内存分配,但我不知道我做错了什么或如何解决这个数组问题。 有没有人知道如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

该阵列的默认编组是unsigned short*,而不是unsigned short[]。你需要应用[MarshalAs]属性来告诉pinvoke marshaller。修正:

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

由于你在数组中返回值,你还必须告诉pinvoke marshaller它需要复制数组值。这需要[Out]属性:

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

请注意,如果你只是将参数声明为ushort [],那么根本不需要,假设结构不包含任何其他字段。