Search code examples
c#c++marshallingstructlayout

Marshaling an unmanaged struct containing a char* member


I am working with a callback function going from unmanged code to my managed C# code. The callback has a parameter void* eventData. EventData could be several different struct types. In my C# code I define eventData as an IntPtr and use Marshal.PtrToStructure to get the struct. For most of the structs I have no issues. However, I am running into issues marshaling this one:

//! Structure for dose parameters

typedef struct
{
    //! the dose in µGrays
    float dose;

    unsigned short nbParameters;
    //! the corresponding parameters specified in the .ini file
    struct Parameters
    {
        //! parameter text
        const char* text;
        //! parameter value
        float value;
    } * parameters;

} DoseParameters;

Here is my C# definition for the struct:

/// <summary>
/// Structure for dose parameters
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct DoseParameters {
    //! the dose in µGrays
    public float dose;

    public ushort nbParameters;
    //! the corresponding parameters specified in the .ini file

    [StructLayout(LayoutKind.Sequential)]
    public struct Parameters{
        //! parameter text        
        public string text;
        //! parameter value        
        public float value;
    }

    [MarshalAs(UnmanagedType.ByValArray)]
    public Parameters[] parameters;
}

The dose and nbParameters values are converted correctly. It's the Parameters array that I am struggling with. The length is always one, and for that one instance, the Parameters.text is nothing intelligible, and Parameters.value is far bigger than it should be.

It seems like it is something to do with the char * being an indeterminate length. Although, I'm new to the StructLayout/MarshalAs stuff so not too sure about it all. I've played with various MarshalAs, LayoutKind.Explicit, and FieldOffset combinations, but have had not success (obviously). I've done some searching and haven't found anything that is similar to my situation.


Solution

  • Fixed this by changing the DoseParamters.parameters member to IntPtr and using JaredPar's answer to this: https://stackoverflow.com/questions/188299/marshal-c-struct-array-into-c-sharp