MarshalDirectiveException

时间:2011-12-20 15:24:26

标签: dllimport

我想在C#中使用C中的非托管代码。

我用这个函数用C代码构建了一个DLL:

struct GetPluginData
{
 int data[22];
};

DLLEXPORT extern "C" __declspec (dllexport) GetPluginData GetDataArray(int number);

在C#中我得到了这段代码:

[StructLayoutAttribute(LayoutKind.Sequential, Pack=1)]
        public unsafe struct GetPluginData
        {
            /// int[22]
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 22, ArraySubType = UnmanagedType.I4)]
            public int[] data;
        }

[DllImport("RBRPlugin.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetDataArray")]
        [return: MarshalAs(UnmanagedType.Struct)]
        public static extern GetPluginData GetDataArray(int number);

在按钮事件或其他地方代码中,我写了这个:

GetPluginData tes = GetDataArray(1);

我收到错误:此方法的类型签名与PInvoke不兼容。

我正在通过谷歌寻找信息,但没有找到结果......

提前致谢!

2 个答案:

答案 0 :(得分:1)

问题:

  • CallingConvertion.StdCall不正确,您没有在C代码中声明函数__stdcall。将其作为CallingConvention.Cdecl。
  • 删除[return:MarshalAs(UnmanagedType.Struct)]属性,这是不正确的。 UnmanagedType.Struct非常不直观,实际上并没用在结构上。
  • 删除Pack属性属性,这里不太可能是正确的,尽管这是无害的。除非使用#pragma pack或/ Zp编译选项,否则C编译器中的默认打包为8。
  • pinvoke marshaller不支持将struct返回为包含嵌入数组的函数返回值。异常的来源。将其声明为fixed int data[22]

答案 1 :(得分:0)

更好的是,正确的代码是:

[DllImport("RBRPlugin.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "GetDataArray")]
public static extern GetPluginData GetDataArray(int number);

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct GetPluginData
{
    public unsafe fixed int data[22];
}

public GetPluginData temp1 = new GetPluginData();

private void button1_Click(object sender, EventArgs e)
{
    GetPluginData test = GetDataArray(1);
    temp1 = test;
    unsafe
    {
        fixed (GetPluginData* p = &temp1)
        {
            p->data[0] = 1;
        }
    }
}