简体   繁体   中英

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. 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).

The function in question is

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

The way I am using PInvoke is as follows:

 [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:

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:

 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. What you're passing in c++ is a pointer to a pointer to a byte array. 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.

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. There's the P/Invoke Interop Assistant tool available for free here .

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; perhaps you need to pass a pre-allocated buffer as well, when using 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.

Original native function call:

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

The way I am using PInvoke is as follows:

[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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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