Calling C DLL function from C# - parameter struct too large or complex to marshal

379 views Asked by At

I have a problem calling a function from a C DLL with C#. I have tried to marshal the struct, but an exception tells me that my struct is too large or too complex to marshal... I have calculated 15256 bytes for the complete size.

The original C function looks like this:

int32_t CN_API SetConfig(int32_t handle, int32_t bId, ModeEnum Mode, ParamStruct params);

The struct that I defined in C# looks like this:

struct ParamStruct
{
    int param1;
    ...
    //Here are some primitve arrays and variables...
    ...
    structArray1[16]
    //    |__...some integers
    //    |__structA
    //            |__...some variables

    int param8

    structB
    //    |__...some integer arrays and a float array
    //    |__structArray2[16]
    //            |__...some variables

    enum param9
    ...
    //here are some more structs and struct arrays
    ...
}

I know that the "syntax" isn´t correct. It´s just that you know what I mean ;).

Now I want to call this function and pass the ParamStruct to it.

My question is, how can I do that? Does anyone of you have a good idea for solving my problem? Is it posible to do it with an IntPtr? Or is the best way to rewrite my structure in C# so, that it is less complex?

If you need more detailed information, please telle me.

1

There are 1 answers

10
PaulF On

I resolved a similar problem by redefining the native method to take a byte * parameter & manually copied the struct to a byte array.

public override void ToByteArray(out byte[] bEeprom)
{
  int arrOffs, arrOffs1, arrOffs2;
  int length = Size();
  int ptrOffset = 0;
  byte[] convString;
  int maxLen;

  IntPtr ptr = Marshal.AllocHGlobal(length);

  Marshal.WriteByte(ptr, ptrOffset, renumerationMode);
  ptrOffset += sizeof(byte);
  Marshal.WriteInt16(ptr, ptrOffset, (short)vendorID);
  ptrOffset += sizeof(short);
  Marshal.WriteInt16(ptr, ptrOffset, (short)productID);
  ptrOffset += sizeof(short);
  Marshal.WriteInt16(ptr, ptrOffset, (short)deviceID);
  ptrOffset += sizeof(short);
  Marshal.WriteByte(ptr, ptrOffset, config);
  ptrOffset += sizeof(byte);
  Marshal.WriteByte(ptr, ptrOffset, eepromVersion);
  ptrOffset += sizeof(byte);
  Marshal.WriteInt16(ptr, ptrOffset, hwVersion);
  ptrOffset += sizeof(short);
  for (arrOffs = 0; arrOffs < configFlags.Length; arrOffs++)
  {
    Marshal.WriteByte(ptr, ptrOffset, configFlags[arrOffs]);
    ptrOffset += sizeof(byte);
  }
......
  Debug.Assert(ptrOffset == length);

  bEeprom = new byte[length];
  Marshal.Copy(ptr, bEeprom, 0, length);
  Marshal.FreeHGlobal(ptr);
}