On Thu, 2007-01-18 at 03:15 -0700, Ted Bullock wrote: > Here is the problem; I am trying to write a binding for the following c > function call: > > void Get_Devices_List(device_entry_t ** const, int * const); > > Notice the location of const. The target is constant, but the pointer > isn't.
You have that backwards: it's a const pointer to pointer to device_entry_t (you read from right to left). Regardless, you don't need to worry about the `const' in this case. > [DllImport ("libmtp")] > internal static extern void LIBMTP_Get_Supported_Devices_List( > out IntPtr devicelist, > out int NumDevices); > > The function I am trying to write is as follows which simply returns an > array of the devices pointed to by device_entry_t: Note that NumDevices > is correctly filled out with a value 44. > > public static DeviceEntry[] SupportedDeviceList() > { > IntPtr DeviceList = IntPtr(0); > int NumDevices = 0; These initializations aren't necessary as you later use `out'. > Get_Devices_List(out DeviceList, out NumDevices); > > > if (NumDevices <= 0) > return new DeviceEntry[]{}; > > DeviceEntry[] Devices = new DeviceEntry[NumDevices]; > > for (int i = 0; i < NumDevices; ++i) > { > IntPtr p = Marshal.ReadIntPtr(DeviceList, i * IntPtr.Size); > //*************** Crash on next line ******************** > Devices[i] =(DeviceEntry)Marshal.PtrToStructure(p,typeof(DeviceEntry)); > } > > return Devices; > } > > Hope somebody can help! Your memory use is wrong. I assume that LIBMTP_Get_Supported_Devices_List()'s deviceList parameter will contain a directly accessible array; that is, C use is: device_entry_t *list; int n; LIBMTP_Get_Supported_Devices_List (&list, &n); for (int i = 0; i < n; ++n) { /* list [i] contains devices */ } This is NOT what your code does. Your code is equivalent to: device_entry_t *list; int n; LIBMTP_Get_Supported_Devices_List (&list, &n); for (int i = 0; i < n; ++n) { device_entry_t e = (device_entry_t) (((char*) list) + n*sizeof(void*)); } You'll notice that this tries to read device_entry_t partially offset from the _actual_ device_entry_t returned, due to using sizeof(void*) (i.e. 4) instead of sizeof(device_entry_t) (i.e. not 4). No wonder things don't work. :-) The solution is to change your loop to use: IntPtr p = Marshal.ReadIntPtr(DeviceList, i * Marshal.SizeOf(typeof(DeviceEntry))); which is equivalent to the C loop body: device_entry_t e = (device_entry) (((char*) list) + n*sizeof(device_entry_t)); which is what `list[n]' effectively compiles to. HOWEVER, this requires that the memory layout of your C# DeviceEntry and the C device_entry_t structures match _identically_, so that Marshal.SizeOf() returns the size of the unmanaged device_entry_t structure. Otherwise, you'll still be improperly accessing the device_entry_t array. You may need to introduce an intermediate structure to make sure your managed & unamanged memory structure layouts match, and then manually convert between your managed helper structure and DeviceEntry. (This would be necessary if e.g. DeviceEntry contains an inline `char' array, and you're unable to use the [MarshalAs(UnmanagedType.ByValArray, SizeConst=N)] attribute on the managed string counterpart. See http://www.mono-project.com/dllimport#Arrays_Embedded_Within_Structures.) - Jon _______________________________________________ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list