简体   繁体   English

C#中的本机C ++ DLL问题

[英]Issue with native C++ dll in C#

I have native C++ dll with function that finds the number of cameras connected to the computer and returns their serial number. 我有原生的C ++ DLL函数,可以找到连接到计算机的摄像机数量并返回它们的序列号。 I am trying to use native C++ dll in C# application but I keep getting the Access Violation error(Attempted to read or write protected memory). 我试图在C#应用程序中使用本机C ++ DLL,但我不断收到访问冲突错误(尝试读取或写入受保护的内存)。

The function in question is 有问题的功能是

    uint32_t GetSerialNumList(char** theBufList, int theBufSize, int theListLength);

The way I am using PInvoke is as follows: 我使用PInvoke的方式如下:

 [DllImport(CameraDll, EntryPoint = "GetSerialNumList", CallingConvention = CallingConvention.Cdecl)]
    private static extern uint GetSerialNumList(out byte[] pBuf, int BufSize, int ListLength);

If I create native C++ application to use the dll and use the function as follows: 如果我创建本机C ++应用程序来使用dll并使用如下函数:

char* theSerialNumb;    
theSerialNumb = (char *) malloc(sizeof(char)* 8);
status = TRI_GetSerialNumList(&theSerialNumb, 8, 1); 

It works fine however, if I use as follows in C# it give me above mentioned error: 它工作正常但是,如果我在C#中使用如下,它给我上面提到的错误:

 byte[] BufList;
 BufList = new byte[8];
 rv = GetSerialNumList(out BufList, 8, 1);

The parameter you're passing in c# is a pointer to a byte array. 您在c#中传递的参数是指向字节数组的指针。 What you're passing in c++ is a pointer to a pointer to a byte array. 你在c ++中传递的是指向字节数组的指针。 Also, in the C++ example, you're passing data to the function, but in the C# example, you're passing it as an out instead of a ref. 此外,在C ++示例中,您将数据传递给函数,但在C#示例中,您将其作为out而不是ref传递。

Although I'm not sure this would work, I would try to create a struct containing a byte array and pass the struct to the external function. 虽然我不确定这会起作用,但我会尝试创建一个包含字节数组的结构,并将结构传递给外部函数。

To answer some of the above comments, these functions typically modify memory passed to it rather than try to allocate additional memory due to the different ways programs create heaps. 为了回答上面的一些注释,这些函数通常会修改传递给它的内存,而不是尝试分配额外的内存,因为程序创建堆的方式不同。

The first thing I'd check is the C# import signature being used. 我要检查的第一件事是使用的C#导入签名。 There's the P/Invoke Interop Assistant tool available for free here . 还有的的P / Invoke的Interop Assistant工具可以免费在这里

Loading your function signature into the tool, translates it to: 将函数签名加载到工具中,将其转换为:

    public partial class NativeMethods {

    /// Return Type: unsigned int
    ///theBufList: char**
    ///theBufSize: int
    ///theListLength: int
    [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="GetSerialNumList")]
public static extern  uint GetSerialNumList(ref System.IntPtr theBufList, int theBufSize, int theListLength) ;

}

The second thing, is that since you are allocating memory for the buffer in the C++/native version; 第二件事是,因为你在C ++ / native版本中为缓冲区分配内存; perhaps you need to pass a pre-allocated buffer as well, when using C#. 也许你需要在使用C#时传递一个预先分配的缓冲区。

Hope this helps. 希望这可以帮助。

Okay, I took pointers from Russell and kvr and did some digging around and following is the scheme that I came up with. 好吧,我接受了Russell和kvr的指点,并进行了一些挖掘,并且遵循的是我想出的方案。

Original native function call: 原始本机函数调用:

uint32_t GetSerialNumList(char** theBufList, int theBufSize, int theListLength);

The way I am using PInvoke is as follows: 我使用PInvoke的方式如下:

[DllImport(CameraDll, EntryPoint = "GetSerialNumList", CallingConvention = CallingConvention.Cdecl)]
        private static extern int GetSerialNumList(ref IntPtr pBuf, int BufSize, int ListLength);

byte[] BufIn;
BufIn = new byte[8 * ListLength];
IntPtr pBuf = IntPtr.Zero;
pBuf = Marshal.AllocHGlobal(8 * ListLength);
Console.WriteLine("Calling GetSerialNumList");
                rv = GetSerialNumList(ref pBuf, 8, ListLength);
                Marshal.Copy(pBuf, BufIn, 0, 8*ListLength);

I feel this is somewhat long, but it gives me the desired result. 我觉得这有点长,但它给了我想要的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM