0

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.

Dan Vogel
  • 3,858
  • 7
  • 41
  • 57
  • `[MarshalAs(UnmanagedType.ByValArray)]` is certainly not correct -- I suspect it should be `UnmanagedType.LPArray` instead. – ildjarn Mar 29 '12 at 20:29

2 Answers2

0

I believe there is a length attribute you can put on the type of the char* in C# to make it convert nicely.

There's actually a conversion tool, the P/Invoke Interop Assistant, you might want to check out (mentioned in [1]). It generates C# code from C code for interop. I used it once for a project and it works pretty well.

[1] http://msdn.microsoft.com/en-us/magazine/cc164193.aspx

EDIT: added tool name

EDIT: http://social.msdn.microsoft.com/Forums/en-us/clr/thread/86412199-da26-4fe4-9450-351f8f3a74b8 similar?

paul
  • 1,655
  • 11
  • 23
0

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

Community
  • 1
  • 1
Dan Vogel
  • 3,858
  • 7
  • 41
  • 57