I have a third party c dll which I want to use in my c# project. I have managed to import one method which reads the header of a file. Now I want to access the method that reads the data. I think the problem is the struct containing an array of strings so I have tried various things such as a list of StringBuilder, creating a list of strings and passing it as an array, to just creating a string array directly (as shown below). After spending a whole day on this already, I no longer know what to do anymore. I am also not sure if I can just pass a decimal array the way I do now (since it is not listed at http://msdn.microsoft.com/en-us/library/ac7ay120(v=vs.100).aspx).
C header of the dll:
enum id_retrieve_enum {
GET_ID = 1,
DO_NOT_GET_ID, // id is in file
NO_ID_IN_FILE,
CREATE_ID // id is not in file
};
struct id_struct {
char **values; // allocated
int size; // optional: DEFAULT_VALUE = NULL_INT
enum id_retrieve_enum retrieve; // optional
};
int importdata(char *fullfilename, int numrows, int numcols, int startrow,
decimal *dataset, struct id_struct *ids);
C# code of enum and struct:
public enum id_retrieve_enum
{
GET_ID = 1,
DO_NOT_GET_ID, // id is in file
NO_ID_IN_FILE,
CREATE_ID // id is not in file
};
[StructLayout(LayoutKind.Sequential)]
public struct id_struct
{
[MarshalAs(UnmanagedType.SafeArray)]
public String[] values;
public int size;
public id_retrieve_enum retrieve;
};
dllimport:
[DllImport("libpandconv.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int importdata(
String fullfilename,
int numrows,
int numcols,
int startrow,
Decimal[] dataset,
[In, Out, MarshalAs(UnmanagedType.Struct)] ref id_struct ids);
Init data and call method:
Decimal[] data = new Decimal[numpoints * highdim];
id_struct ids = new id_struct();
ids.retrieve = (hasid.Equals(1)) ? id_retrieve_enum.GET_ID : id_retrieve_enum.CREATE_ID;
ids.values = new String[numpoints];
importdata(inputfilename, numpoints, highdim, startrow, data, ref ids);
where inputfilename has already been marshalled and the numpoints, highdim and startrow are already returned by importheader method which I have already imported.
IntPtrforvaluesand marshal by hand. A C++/CLI layer would be a possible route also. Who allocates this array of strings and how is it expected to be freed?IntPtrbut it did not work at the time. I am going to try that again now, thanks!ids.values = (char**) malloc (numpoints * sizeof(char*));and they also free the memory at some later point. So I am trying to do the same now by using IntPtr instead of the String[] and usingids.values = Marshal.AllocHGlobal(numpoints). I have never worked with the Marshal class (or dllimport for that matter) so I don't really know what I am doing so am just trying out different things. I also do not know how to make the deallocation occur on the same heap...