【问题标题】:Have Error : PInvokeStackImbalance with dll有错误:带有 dll 的 PInvokeStackImbalance
【发布时间】:2018-08-30 17:49:38
【问题描述】:

我目前正在开发一个从不同设备获取数据的 USB 设备。

typedef struct 有问题,我无法在 c# 中重现。

在 Dll 的源代码中,我有这个:

typedef struct _UF01_INFORMATIONS{
        BYTE Type[MAX_MODULE];
        BYTE Nombre_Module;
        BYTE Nb_Voies[MAX_MODULE];
        BYTE Modele[MAX_MODULE];
        char *Name[MAX_MODULE];
        char *Comments[MAX_MODULE];
        BOOL UseInterrupt;
} UF01_INFORMATIONS, *PUF01_INFORMATIONS;

MAX_MODULE equals 8 ^^

这是我的代码:

    [DllImport(@"C:\Program Files (x86)\DLL\UFDF.dll", EntryPoint = "UF01_OpenDevices", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_OpenDevices(byte* devices);

    [DllImport(@"C:\Program Files (x86)\DLL\UFDF.dll", EntryPoint = "UF01_CloseAll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern void UF01_CloseAll();

    [DllImport(@"C:\Program Files (x86)\SELIAtec\DLL\UFDF.dll", EntryPoint = "UF01_UD01_8Entrees", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_UD01_8Entrees(byte Device, byte module, byte* data);

    [DllImport(@"C:\Program Files (x86)\DLL\UFDF.dll", EntryPoint = "UF01_UD01_8Entrees", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_GetInfosModule(byte Device, bool Watchdog, [In, Out] _UF01_INFORMATIONS infos);

    public Form1()
    {
        InitializeComponent();

    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
    public struct _UF01_INFORMATIONS
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public unsafe byte[] Type;
        [MarshalAs(UnmanagedType.I1)]
        public unsafe byte Nombre_Module;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public unsafe byte[] Nb_Voies;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public unsafe byte[] Modele;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public unsafe string[] Name;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public unsafe string[] Comments;
        [MarshalAs(UnmanagedType.I1)]
        public unsafe bool UseInterrupt;
    }


    private unsafe void button1_Click(object sender, EventArgs e)
    {
        byte nb_Device;

        _UF01_INFORMATIONS m_infos = new _UF01_INFORMATIONS();
        m_infos.Type = new byte[8];
        m_infos.Nb_Voies = new byte[8];
        m_infos.Modele = new byte[8];
        m_infos.Name = new string[8];
        m_infos.Comments = new string[8];
        m_infos.Nombre_Module = 0;
        m_infos.UseInterrupt = false;


        if (UF01_OpenDevices(&nb_Device))
        {
            this.label1.Text = "Nombre de CPU's : " + nb_Device;

            UF01_GetInfosModule(nb_Device, false, m_infos); //<== Here is the ERROR

            label2.Text = "Nombre de modules : " + m_infos.Nombre_Module;
         }
    }

“UF01_GetInfosModule”行的错误是:“PInvoke 托管签名与非托管签名不同”

我正在搜索,但找不到出现此错误的原因。

感谢您的帮助!

【问题讨论】:

  • 您好,感谢您的回答。当我使用 ref 参数时,我没有收到任何错误,但函数 UF01_GetInfosModule 现在返回 false ...
  • 好像数据不能写入ref变量。我不知道为什么...

标签: c# c++ unmanaged


【解决方案1】:

我的代码现在是:

    public partial class Form1 : Form { 

    [DllImport(@"C:\Program Files (x86)\SELIAtec\UF01\UF01.dll", EntryPoint = "UF01_OpenDevices", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_OpenDevices(ref byte devices);

    [DllImport(@"C:\Program Files (x86)\SELIAtec\UF01\UF01.dll", EntryPoint = "UF01_CloseAll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern void UF01_CloseAll();

    [DllImport(@"C:\Program Files (x86)\SELIAtec\UF01\UF01.dll", EntryPoint = "UF01_UD01_8Entrees", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_UD01_8Entrees(byte Device, byte module, ref byte data);

    [DllImport(@"C:\Program Files (x86)\SELIAtec\UF01\UF01.dll", EntryPoint = "UF01_UD01_8Entrees", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_GetInfosModule(byte Device, bool Watchdog, ref _UF01_INFORMATIONS infos);

    [DllImport(@"C:\Program Files (x86)\SELIAtec\UF01\UF01.dll", EntryPoint = "UF01_UA01_Entrees", CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
    unsafe static extern Boolean UF01_UA01_Entrees(byte Device, byte Module, ref ushort[] TableData_12bit);

    public Form1()
    {
        InitializeComponent();

    }

    [StructLayout(LayoutKind.Sequential)]
    public struct _UF01_INFORMATIONS
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] Type;
        [MarshalAs(UnmanagedType.U1)]
        public byte Nombre_Module;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] Nb_Voies;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] Modele;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public string[] Name;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public string[] Comments;
        [MarshalAs(UnmanagedType.I1)]
        public bool UseInterrupt;
    }


    private unsafe void button1_Click(object sender, EventArgs e)
    {
        byte nb_Device = 0;
        ushort[] data = new ushort[8]; 

        _UF01_INFORMATIONS m_infos = new _UF01_INFORMATIONS();
        m_infos.Type = new byte[8];
        m_infos.Nb_Voies = new byte[8];
        m_infos.Modele = new byte[8];
        m_infos.Name = new string[8];
        m_infos.Comments = new string[8];
        m_infos.Nombre_Module = 0;
        m_infos.UseInterrupt = false;

        if (UF01_OpenDevices(ref nb_Device))
        {
            this.label1.Text = "Nombre de CPU's : " + nb_Device;

            if (UF01_GetInfosModule(nb_Device, false, ref m_infos))
                label2.Text = "Nombre de modules : " + m_infos.Nombre_Module.ToString();

            if (UF01_UA01_Entrees(nb_Device, 1, ref data))
                label3.Text = "Donnee : " + data[0].ToString();
        }
    }
}

名为 UF01_OpenDevices 的第一个函数有效。它在 ref 变量中返回设备的数量。但其他 2 个功能不起作用。他们返回错误。 不知道为什么……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多