Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert native C++ memory into C# structure?

I have the following native function interface in C++:

int func1(void* param, int sizeOfParam).

In documentation the following example of call is provided:

typedef struct
{
    int x;
    int y;
    int width;
    int height;
} Rect;

Rect rect;

int func1((void*)&rect, sizeof(rect));

I need to call this function from C# code.

I have the following header in C# from developers of native library:

[DllImport(NATIVE_DLL_NAME, 
 CallingConvention = CallingConvention.Cdecl, 
 EntryPoint = "func1")]
private static extern int func1(IntPtr param, int sizeOfParam);

I also have the following C# structure Rect:

public struct Rect
{
    int x;
    int y;
    int width;
    int height;
};

I need to call func1 in C# code and pass Rect:

I do the following:

Rect rect = new Rect();
int rectSize = System.Runtime.InteropServices.Marshal.SizeOf(rect);

func1(???, rectSize);

What to place in position of ??? where rect should be passed (but it is not possible because of incompatible types)?

It seems that IntPtr should be passed and then converted to struct rect. How to achieve this?

(rect is output parameter here)

UPDATE:

It is desired not to change signatures of C++ code and C# wrappers - it is third part code.
Moreover it is not always variable of Rect is passed as first param of func1

like image 266
sergtk Avatar asked Oct 03 '11 10:10

sergtk


1 Answers

You changed the rules of the game to disallow modifications to the C# code. And so the P/invoke must be of this form:

private static extern int func1(IntPtr param, int sizeOfParam);

In that case you need to do the marshalling by hand:

int size = Marshal.SizeOf(typeof(Rect));
IntPtr param1 = Marshal.AllocHGlobal(size);
try
{
    func1(param1, size);
    Rect rect = (Rect)Marshal.PtrToStructure(param1, typeof(Rect));
}
finally
{
    Marshal.FreeHGlobal(param1);
}
like image 116
David Heffernan Avatar answered Sep 30 '22 03:09

David Heffernan