Ian Auty
Ian Auty

Reputation: 847

Pointer to a pointer in F#

I'm currently trying to learn the P/Invoke capabilities of .NET, particularly in F#. A C function that I'm trying to call requires a parameter which is a 'pointer to a pointer' and I'm struggling to find which operator to use to represent this in F#.

After doing some reading, particularly this blog post, I'm lead to believe that in .NET languages, it is better to represent pointer parameters with a & instead of * such that they are 'Managed Pointers' (if someone could clarify for me any use cases whereby I shouldn't be using the Managed Pointers then that would be great too!). Therefore, so far, I've tried && which is incorrect as it represents a Boolean AND, and I've also tried ** which would match the 'C' style representation of a pointer to a pointer.

I believe that in C#, you can represent this in a similar way to the 'C' style, i.e int** q;.

Would anyone know how to do anything similar in F# please? Particularly in extern definitions.

Thank you.

Update

Apologies for not being more specific - this is to a struct type.

To be precise on what I'm doing here - I'm trying to replicate the struct MMAL_BUFFER_HEADER_T found here for a project I'm working on with the Raspberry Pi Camera Module. This struct is then used in the following function. The address of the pointer will be set upon returning from the function.

Update 2 Thinking out loud here - would using System.IntPtr& represent this in the correct way?

Upvotes: 1

Views: 488

Answers (2)

Ian Auty
Ian Auty

Reputation: 847

Just in case anyone else happens to come across this question, I have ended up using a nativeint& to represent the multiple indirection required for the function call. The function itself allocates memory for me so I am happy using this method going forward. Thanks again to all who helped me get on my way with this.

Upvotes: 0

Bent Tranberg
Bent Tranberg

Reputation: 3470

Too much effort for me to check this properly, but try this.

You have to make sure you get the types and the source attributes right of course. Is Sequential and Cdecl correct? If you don't need referencing fields of the struct(s) in F#, in other words treating it like an opaque type, then you can possibly get away with using nativeint (with or without ampersand?) in the function header instead, same way you would use void pointer in C.

open System.Runtime.InteropServices

type uint32_t = uint32 // likely correct type, but you must check
type MMAL_STATUS_T = int32 // replace with correct type
type MMAL_PORT_T = int32 // replace with correct type

#nowarn "9"
[<Struct; StructLayout(LayoutKind.Sequential)>]
type MMAL_BUFFER_HEADER_T =
    val next: MMAL_BUFFER_HEADER_T ref // will ref work here, or should it be byref<MMAL_BUFFER_HEADER_T>?
    val priv: nativeint // or you could use a type (with ref?) here also
    val cmd: uint32_t // assuming uint32_t is uint32
    // etc
    val typ: MMAL_BUFFER_HEADER_TYPE_SPECIFIC_T ref
    val user_data: nativeint // void pointer in C

[<DllImport("SomeDll.dll", CallingConvention=CallingConvention.Cdecl)>]
extern MMAL_STATUS_T mmal_port_event_get(MMAL_PORT_T port, MMAL_BUFFER_HEADER_T& buffer, uint32_t event)

Upvotes: 1

Related Questions