c# - 在 C# 中使用 C++ DLL

标签 c# c pinvoke

我的程序需要控制一个硬件。供应商提供了一个为 C/C++ 语言设计的 DLL。 除了以下功能之外,大多数功能都通过了我的测试:

int32 ni845xSpiWriteRead(NiHandle DeviceHandle,
                         NiHandle ConfigurationHandle,
                         uInt32   WriteSize,
                         uInt8  * pWriteData,
                         uInt32 * pReadSize,
                         uInt8  * pReadData);

这个函数的文档在这里:

  • 输入 NiHandle 设备句柄

    从 ni845xOpen 返回的设备句柄。

  • NiHandle 配置句柄

    从 ni845xSpiConfigurationOpen 返回的配置句柄。

  • uInt32 写入大小

    要写入的字节数。这必须是非零的。

  • uInt8 * pWriteData

    要写入的数据字节。

  • 输出 uInt32 * pReadSize

    指向读取字节数的指针。

  • uInt8 * pReadData

    指向已读取字节的字节数组的指针 已存储。

我的 C# 代码在这里:

[DllImport("Ni845x", CallingConvention = CallingConvention.Cdecl)]
public static extern int ni845xSpiWriteRead(
                                                long DeviceHandle, //In 
                                                long ConfigurationHandle, //In
                                                int WriteSize, //In
                                                IntPtr pWriteData, //In
                                                IntPtr pReadSize, //Out
                                                IntPtr pReadData //Out
                                                );

我总是遇到 AccessViolationException 异常。我猜这是由指针输入/输出参数引起的。

调用Swrapper.ni845xSpiWriteRead()的代码在这里:

public void WriteData(int length, int[] writeArray)
        {
            byte[] writeDate = new byte[8];

            int writeSize = writeDate.Length;

            try
            {
                //Define pointers
                IntPtr writeDataPointer = Marshal.AllocHGlobal(writeDate.Length);
                IntPtr readDataSizePointer = Marshal.AllocHGlobal(writeDate.Length);
                IntPtr readDataPointer = Marshal.AllocHGlobal(writeDate.Length);

                //Copy value to write data pointer
                Marshal.Copy(writeDate, 0, writeDataPointer, writeDate.Length);

                int state = Ni845xNativeMethods.ni845xSpiWriteRead(_niHandle, _niConfigrationHandle, writeSize, writeDataPointer,readDataSizePointer,readDataPointer);

                this.CheckStatus(state);

            }
            catch (Exception)
            {
                throw;
            }
        }

最佳答案

最有可能的 p/invoke 应该是:

[DllImport("Ni845x", CallingConvention = CallingConvention.Cdecl)]
public static extern int ni845xSpiWriteRead(
    IntPtr DeviceHandle,
    IntPtr ConfigurationHandle,
    uint WriteSize,
    [In] byte[] WriteData,
    out uint ReadSize,
    [Out] byte[] ReadData
);

您需要分配足够长度的 byte[] 以用作 ReadData 参数。想必您知道如何执行此操作。

我从表面上看,ReadSize 是一个输出参数。但是,如果它既是 in 又是 out,则将其声明为 ref

关于c# - 在 C# 中使用 C++ DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24795988/

相关文章:

C# 使用 Linq 填充 TreeView

c# - MVC 3 图片上传路径

c++ - 宏 ((void(*)())0)() 是什么意思?

用于大型 C 库的 C++/CLI 或 C# P/Invoke,调用外部函数

c# - 我可以使用 ADFS 2.0 对特定用户进行 SQL Server 身份验证吗?

c# - 碰撞时传送玩家对象不起作用

c++ - 如何从应用程序所在的同一文件夹运行 exe

c - 复制结构时没有获得正确的值

c# - P/Invoke 和 C# 的自定义调用约定

c# - WPF C# 应用程序中的 C++ Dll