Native code:

typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, size_t *olen); typedef struct { mbedtls_entropy_f_source_ptr f_source; } mbedtls_entropy_source_state; 

How to properly describe such an unmanaged structure in managed code?

    2 answers 2

    The structure is very simple to describe: there is only one field in it. I understand that problems have arisen with the definition of the type of this field.

    First you need to create a delegate and [UnmanagedFunctionPointer(CallingConvention.Cdecl)] attribute [UnmanagedFunctionPointer(CallingConvention.Cdecl)] to it to tell the marshaler that this delegate must be converted into a pointer to the cdecl function (and vice versa) when passed to unmanaged code:

     [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int mbedtls_entropy_f_source_ptr( 

    Next, the first parameter. It is a void* type parameter, with a description of the “Callback-specific data pointer” —that is, it can contain anything, depending on the specific source of entropy.

    Most likely, it should be declared as IntPtr data - but there is also an option to consider as a link to the structure ( ref SomeData data ).

    The second parameter plays the role of an array to fill in — an array of it should be done by specifying the transfer type LPArray. Also, the marshaler will need a length in order to properly “decorate” the incoming pointer as an array — it will be necessary to mention that it is passed in the third parameter. Alternatively, you can accept it as an IntPtr and work with it through the Marshall class.

    The third parameter is of type size_t (unsigned number the size of a pointer) - we replace it with UIntPtr .

    The fourth parameter has a pointer type - it can be accepted as IntPtr . But in accordance with the semantics, it is better to specify it as out UIntPtr .

    Here's what happened in the end:

     [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int mbedtls_entropy_f_source_ptr( IntPtr data, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] output, UIntPtr len, out UIntPtr olen); struct mbedtls_entropy_source_state { mbedtls_entropy_f_source_ptr f_source; } 

      Maybe so

       public struct mbedtls_entropy_source_state { public Delegate mbedtls_entropy_f_source; }