[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