Question

Here's the line I get the execution error:

NimbieImportedFunctions.BS_Robots_Connect(
    out robotCount, out robotIDs, out robotTypes, out robotReadys);

And the DllImport itself:

[DllImport("BSRobots20.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 BS_Robots_Connect(
    out int nRobotCount,
    out int[] pnRobotIDS,
    out int[] pnRobotTypes,
    out bool[] pbRobotReadys);

And from the header file:

extern "C" __declspec(dllexport) DWORD BS_Robots_Connect(
        int *nRobotCount,
        int *pnRobotID,
        int *pnRobotType,
        bool *pnRobotReady
    );
//
//  Description:
//      Function to connect all online robots.
//
//  Parameters:
//      nRobotCount  [out]  Pointer to an integer that receives the number of robots.
//      pnRobotID    [out]  Pointer to an array of integer that receives the robot IDs.
//      pnRobotType  [out]  Pointer to an array of integer that receives the robot types.
//
//  Return:
//      BS_ROBOTS_OK     If the function succeeds with no error.
//      BS_ROBOTS_ERROR  If the function fails with any error occurred.
//
///////////////////////////////////////////////////////////////////////////////

And the error I get:

The runtime has encountered a fatal error. The address of the error was 
at 0x72c4898e, on thread 0xdf0. The error code is 0xc0000005. 
This error may be a bug in the CLR or in the unsafe or non-verifiable portions
of user code. Common sources of this bug include user marshaling errors for
COM-interop or PInvoke, which may corrupt the stack.

Sometimes, I also get an AccessViolationException. I'm so incredibly unsure as to what's going on. Please help me SO!

Was it helpful?

Solution

Your p/invoke is incorrect. It should, perhaps, read:

[DllImport("BSRobots20.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern uint BS_Robots_Connect(
    out int nRobotCount,
    [Out] int[] pnRobotIDS,
    [Out] int[] pnRobotTypes,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)]
    [Out] bool[] pbRobotReadys
);

It is plausible that nRobotCount should be ref rather than out. Determine that based on whether or not you need to pass information into the function. And are you sure that pbRobotReadys is an array? If not then use out bool or ref bool.

So perhaps what you need is:

[DllImport("BSRobots20.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern uint BS_Robots_Connect(
    ref int nRobotCount,
    [Out] int[] pnRobotIDS,
    [Out] int[] pnRobotTypes,
    [MarshalAs(UnmanagedType.U1)]
    out bool pbRobotReadys
);

To get to the bottom of this you'll need to study the documentation a little more, and perhaps refer to any C++ example code that you can find.

You will need to allocate arrays before calling the function. I cannot tell from here how exactly you need to allocate the arrays. Presumably you know how large they need to be.


Why was your version wrong? Well, the way to think about this is that a C# array is already a reference. By passing the array using out you are passing a pointer to a pointer. In other words, one level of indirection too far.

Another way to think about this is that you were asking the unmanaged code to create managed arrays. And that is something that it manifestly cannot do.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top