[Mono-list] Hang on JIT-ing fn with P/Invoke?
Andy Hume
andyhume32 at yahoo.co.uk
Fri Aug 10 10:03:02 EDT 2007
Jonathan Pryor wrote:
> On Thu, 2007-08-09 at 14:01 +0100, Andy Hume wrote:
> > There may well be something wrong with the P/Invoke
> definitions :-,),
>
> I have no idea why it's hanging, but the P/Invoke definitions
> *are* wrong:
>
Thanks both. I need to go and do some reading...! (mono-project.com
seems to be down at the moment).
[...]
> Never use reference types as the return value of a P/Invoke
> (in this case, both sdp_list_t and uuid_t are reference
> types, as you declared them `class', not `struct'). The
> reason for this is that the runtime will allocate a class
> instance on the GC heap, copy over the class/structure
> contents, and free the returned memory [1]. This is almost
> *never* what you want, as the memory may (probably will) be
> freed by the wrong function, thus corrupting the heap. Not good.
>
> The correct thing to do is to use IntPtr as the return value,
> and marshal the IntPtr into the appropriate type using
> Marshal.PtrToStructure().
>
> So a more accurate binding would be:
>
> struct BluezUuid {
> public byte type;
> public Guid uuid128;
> }
>
> static class NativeMethods {
> const string BluetoothLibrary = "libbluetooth";
>
> // sdp_list_t* sdp_list_append(sdp_list_t* list, void*
> d);
> internal static extern IntPtr sdp_list_append(IntPtr
> list,
> IntPtr d);
>
> // uuid_t* sdp_uuid16_create(uuid_t* uuid, uint16_t
> data);
> internal static extern IntPtr sdp_uuid16_create(
> ref BluezUuid u, ushort val);
> }
>
> With usage:
>
> IntPtr uuid =
> UnixMarshal.AllocHeap(Marshal.SizeOf(typeof(BluezUuid));
> NativeMethods.sdp_uuid16_create(uuid, 0x0100);
>
> IntPtr search_list =
> NativeMethods.sdp_list_append(IntPtr.Zero,
> uuid);
>
> Yes, this style of programming is horribly unsafe (IntPtrs everywhere!
> No compiler-checked type safety!), but you need to conform to
> what the existing code is expecting, in this case
> malloc(3)-allocated memory of the appropriate size, with no
> inappropriate implicit marshaling.
>
Three quick questions if you happen to know the answers:
1. Is UnixMarshal.AllocHeap required rather than a call to
Marshal.AllocHGlobal?
2. To add some level of type compiler-checked type safety, could one not
even replace instances of IntPtr with a set of structs each containing
only an IntPtr? e.g.
struct PSdpList{
IntPtr ptr;
}
(Must go and read that document!)
3. Is the format of System.Guid likely to be the same format as a
SDP/general Linux expects it?
Andy
More information about the Mono-list
mailing list