Reputation: 847
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
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
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