Swig and C#: cannot assign value to struct array member

70 Views Asked by At

The C++ struct has one fixed 2d char array as member

typedef struct ReqSubscribeField
{
    char routing_key[100][56];
}ReqSubscribeField_t;

and I used Swig to generate the following C# class representing the struct

public class ReqSubscribeField_t : global::System.IDisposable {
  private global::System.Runtime.InteropServices.HandleRef swigCPtr;
  protected bool swigCMemOwn;

...

  public SWIGTYPE_p_a_56__char routing_key {
    set {
      libnhmdapiPINVOKE.ReqSubscribeField_t_routing_key_set(swigCPtr, SWIGTYPE_p_a_56__char.getCPtr(value));
    } 
    get {
      global::System.IntPtr cPtr = libnhmdapiPINVOKE.ReqSubscribeField_t_routing_key_get(swigCPtr);
      SWIGTYPE_p_a_56__char ret = (cPtr == global::System.IntPtr.Zero) ? null : new SWIGTYPE_p_a_56__char(cPtr, false);
      return ret;
    } 
  }

  public ReqSubscribeField_t() : this(libnhmdapiPINVOKE.new_ReqSubscribeField_t(), true) {
  }

}

and the following swig type representing the fixed size char array

public class SWIGTYPE_p_a_56__char {
  private global::System.Runtime.InteropServices.HandleRef swigCPtr;

  public SWIGTYPE_p_a_56__char(global::System.IntPtr cPtr, bool futureUse) {
    swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
  }

  protected SWIGTYPE_p_a_56__char() {
    swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
  }

  internal static global::System.Runtime.InteropServices.HandleRef getCPtr(SWIGTYPE_p_a_56__char obj) {
    return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
  }
}

and I want to assign values to routing_key member and use a parameter of a function.

I tried to assign values to **routing_key ** with following code:

IntPtr[] ptrs = new IntPtr[100];
string inst = "abcd".PadRight(56, '\0');
Console.WriteLine(inst.Length);
ptrs[0] = Marshal.StringToHGlobalAnsi(inst);
for (int i = 1; i < 100; i++)
{
    ptrs[i] = Marshal.StringToHGlobalAnsi(string.Empty.PadRight(56, '\0'));
}

GCHandle gch = GCHandle.Alloc(ptrs, GCHandleType.Pinned);
IntPtr inputs = gch.AddrOfPinnedObject();
ReqSubscribeField_t subscribeField_T = new ReqSubscribeField_t();
SWIGTYPE_p_a_56__char swigInstruments = new SWIGTYPE_p_a_56__char(inputs, true);
subscribeField_T.routing_key = swigInstruments;

or

char[,] routeKeys = new char[100, 56];
routeKeys[0, 0] = 'a';
routeKeys[0, 1] = 'b';
routeKeys[0, 2] = 'c';
routeKeys[0, 3] = 'd';
routeKeys[0, 4] = '\0';

GCHandle gch = GCHandle.Alloc(routeKeys, GCHandleType.Pinned);
IntPtr inputs = gch.AddrOfPinnedObject();

ReqSubscribeField_t subscribeField_T = new ReqSubscribeField_t();
SWIGTYPE_p_a_56__char swigInstruments = new SWIGTYPE_p_a_56__char(inputs, true);
subscribeField_T.routing_key = swigInstruments;

Neither worked, the C# setter did not work, there is no data in the variable. Please help!!!

1

There are 1 best solutions below

0
SongXiangGong On

Found a solution, I just need to create a helper function

void DisplayDataHelper(char *data[], int cnt)
    {
        ReqSubscribeField_t request = {0};
        for (int i = 0; i < cnt && i < 100; i++) {
            for (int j = 0; j < 56; j++) {
                if (data[i][j] == '\0') {
                    for (int k = j; k < 10; k++) {
                        request.routing_key[i][k] = '\0';
                    }
                    break;
                }
                request.routing_key[i][j] = data[i][j];
            }
        }
        
        this->DisplayData(request);
    };

and in C#, use

List<string> instruments = new List<string>() { "abc", "def", "ghi" };
            IntPtr[] ptrs = new IntPtr[instruments.Count];
            for (int i = 0; i < instruments.Count; i++)
            {
                ptrs[i] = Marshal.StringToHGlobalAnsi(instruments[i]);
            }

            GCHandle gch = GCHandle.Alloc(ptrs, GCHandleType.Pinned);
            IntPtr inputs = gch.AddrOfPinnedObject();
            SWIGTYPE_p_p_char swigInstruments = new SWIGTYPE_p_p_char(inputs, true);
            myTest.DisplayDataHelper(swigInstruments, 3);

then it works, seems like swig typemap has some bug with fixed length array.