Friday, 15 August 2014

Marshal struct from C to C# -



Marshal struct from C to C# -

edit: oversimplified example... in real code assigning values strmystringx without correctly using wcscpy_s, instead of assigning values passing pointer, out of scope time values beingness marshaled managed code...

i'm trying marshal struct 3 string properties c c#, can't definition of struct right in c#. of properties print garbage. marshaling wrong or properties have wrong type?

my custom structure:

typedef struct _my_struct_string { lpwstr strmystring1; lpwstr strmystring2; lpwstr strmystring3; }my_struct_string, *pmy_struct_string;

my c function returns array of pointers struct:

bool benumeratestring(out long &i_arr_size, out pmy_struct_string* &parrstringstruct) { // [...] function simplified demonstrate building pointer array of struct* long i_arr_size = 3 pmy_struct_string *ptr_arr_string = (pmy_struct_string *)malloc(sizeof(pmy_struct_string)* i_arr_size); (int = 0; < i_arr_size; i++) { ptr_arr_string[i] = (pmy_struct_string)malloc(sizeof(my_struct_string)); ptr_arr_string[i]->strmystring1 = l"string 1"; // work. in real code assigning values array , mistakenly passed pointer rather doing wcscpy_s ptr_arr_string[i]->strmystring2 = l"string 2"; ptr_arr_string[i]->strmystring3 = l"string 3"; } parrstringstruct = ptr_arr_string; homecoming true; }

c#:

//import dll function [dllimport("my.dll", setlasterror = true, charset = charset.unicode, entrypoint = "benumeratestring")] internal static extern bool benumeratestring(out long count, out intptr parrstringstruct); // define c# equivalent of c struct [structlayout(layoutkind.sequential, charset = charset.unicode)] internal struct my_struct_string { [marshalasattribute(unmanagedtype.byvaltstr, sizeconst = 8)] public string strmystring1; [marshalasattribute(unmanagedtype.byvaltstr, sizeconst = 8)] public string strmystring1; [marshalasattribute(unmanagedtype.byvaltstr, sizeconst = 8)] public string strmystring1; } [...] // code marshal (try... grab etc removed succinctness) intptr parrstruct = intptr.zero; long lcount = 0; bool bresult = false; bresult = benumeratestring(out lcount, out parrstruct); if (!bresult) { // marshal deref pointer intptr[] parrstructlist = new intptr[lcount]; (ulong = 0; < (ulong)lcount; i++) { parrstructlist[i] = marshal.readintptr(parrstruct, marshal.sizeof(typeof(intptr)) * (int)i); } // marshal pointers struct var lstmystringstrct = new list<my_struct_string>(parrstructlist.length); foreach (intptr ptr in parrstructlist) { lstmystringstrct.add((my_struct_string)marshal.ptrtostructure(ptr, typeof(my_struct_string))); } // enumerate struct foreach (my_struct_string mystr in lstmystringstrct) { // of these outputs garbage console.writeline("strmystring1: " + mystr.strmystring1); console.writeline("strmystring2: " + mystr.strmystring2); console.writeline("strmystring3: " + mystr.strmystring3); } }

i see 1 problem. you're c++ construction uses lpwstr (pointers) whereas you're c# code expecting fixed size char arrays.

change strings from:

[marshalasattribute(unmanagedtype.byvaltstr, sizeconst = 8)] public string strmystring1;

which used when c++ construction defined like:

char strmystring1[8];

to:

[marshalasattribute(unmanagedtype.lpwstr)] public string strmystring1;

c# c marshalling

No comments:

Post a Comment