我正在尝试访问并更改DLL中的结构中的元素。我已经按照这个示例介绍了如何使用DLL中的struct
:http://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#中复制我的结构时,我必须非常小心内存分配,但我不知道我做错了什么或如何解决这个数组问题。 有没有人知道如何解决这个问题?
答案 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 [],那么根本不需要,假设结构不包含任何其他字段。