2

I have a C++ function in a DLL which takes a pointer to a struct, JPInfo, which in the function is filled with data received from a server, the layout of the C++ struct is as seen below:

typedef struct JP
{
    unsigned char type;
    DWORD value;
} JP;

typedef struct JPInfo
{
    JP jps[3];
    _int16 ConT;
    _int16 CallT;
    unsigned char ret;
    unsigned char count;
    unsigned char JPOffset;
    unsigned char JPPeriod;
} JPInfo;

The function is exported in the DLL like so:

__declspec(dllexport) DWORD __stdcall GetJPInfo(JPInfo* jpi, DWORD time);

The function takes a pointer to a JPInfo struct, I have tried to emulate this struct in C#

[StructLayout(LayoutKind.Sequential, Size = 5), Serializable]
public struct JP
{
    byte type;
    int value;
}

[StructLayout(LayoutKind.Sequential,Size=23),Serializable]
public struct JPInfo
{
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

I attempt to call the function from C# like so:

[DllImport("DLLImp.dll")]
    unsafe public static extern int GetJP(ref JPInfo jpi, int time);
// then in main...
JPInfo jpi = new JPInfo;
GetJackpotValues(ref jpi, 4000);

I get an unhandled exception of type "System.ExecutionEngineException". I can't have a fixed size array of JP structs in my JPInfo struct, so I don't know how to approach this.

Thanks.

1
  • Try not to specify sie explicitly and the default Marshaller do it stuff. (Size=23,5 etc) Commented Mar 1, 2012 at 14:17

2 Answers 2

4

Have you tried removing your Size attributes on your structs? I haven't had to specify a Size when doing something similar. For your array properties, try attributing them like:

[StructLayout(LayoutKind.Sequential)]
public struct JPInfo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Hmm I'm not getting an error now but the struct doesn't get filled, in the DLL a direct byte for byte copy is performed so the order of the items in the struct is vital, does the way I've declared the struct gaurantee that the members in the struct will be in that same order in memory?
Yes, this is a way to go. I would also initialize array on creation doing JP[] jps = new JP[3];.
By specifying LayoutKind.Sequential, the memory will be laid out in the order in which you define the struct properties in your .NET app. Having a dynamic array size wouldn't make sense to me since you have to send a precise memory allocation across the pipe.
@Krizz Why would you need to do that? The pinvoke marshaller will initialise with default values so the step that you outline is simply not needed.
2

Assuming that the C++ structs are packed, your C# structs should look like this:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct JP
{
    byte type;
    uint value;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct JPInfo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    JP[] jps;
    Int16 ConT;
    Int16 CallT;
    byte ret;
    byte count;
    byte JPOffset;
    byte JPPeriod;
}

On the other hand, if they are not packed then remove the Pack parameter to the StructLayout attribute. You should look for a #pragma pack statement in the C++ header file to understand whether or not the C++ structs are packed.

I'm guessing that the C++ structs are packed because you said that they are mapped onto data received from the server.

Your import should be like so:

[DllImport("DLLImp.dll")]
public static extern uint GetJP(ref JPInfo jpi, uint time);

A DWORD translates to uint rather than int and there is no need for unsafe code here.

1 Comment

Absolutely perfect! Thanks David.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.