I have to replicate some C++ in C#. More specifically I have to create the equivalent of converting between pinit_param to pinit_param_g. The definition of pinit_param and pinit_param_g are below. C++:
typedef struct init_param {
int size;
HWND hwnd;
} init_param, *pinit_param;
typedef struct init_param_g {
int size;
HWND hwnd;
GUID appKey;
} init_param_g, *pinit_param_g;
extern "C" LIBRARY_API int __cdecl api_init(pinit_param param);
...
init_param_g paramg;
memset(¶mg, 0, sizeof(init_param_g));
paramg.size = sizeof(init_param_g);
paramg.hwnd = GetConsoleHwnd();//not relevant what implementation GetConsoleHwnd() has
paramg.applicationKey = APP_GUID;//not relevant what value APP_GUID has
api_init((pinit_param)¶mg);
What I've done in C#:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
public struct init_param
{
public int size;
public IntPtr hwnd;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
public struct init_param_g
{
public int size;
public IntPtr hwnd;
public Guid appKey;
}
[DllImport...]
public static extern Int32 api_init(ref init_param param);
.....
init_param_g paramg = new init_param_g();
paramg.size = Marshal.SizeOf(typeof(init_param_g));
paramg.hwnd = HWND;
paramg.appKey = APP_GUID;
var ret = api_init(ref (init_param)paramg);//error
.... or
init_param paramg = new init_param();
paramg.iSize = Marshal.SizeOf(typeof(init_param));
paramg.hwnd = HWND;
var ret = api_init(ref paramg);//the code compiles but initialization is not complete
I've tried to make init_param_g to inherit from init_param but you can't do that in C#. I've tried to convert using (init_param) in front of the variable or (ref init_param). Compile error both times.
The simplest way is to provide custom type cast operator (implicit or explicit as you like). The following example shows implicit operator
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
public struct init_param
{
public int size;
public IntPtr hwnd;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
public struct init_param_g
{
public int size;
public IntPtr hwnd;
public Guid appKey;
public static implicit operator init_param(init_param_g self)
{
return new init_param()
{
size = Marshal.SizeOf(typeof(init_param_g)),
hwnd = self.hwnd,
};
}
}
Usage:
init_param_g paramg = new init_param_g();
paramg.size = Marshal.SizeOf(typeof(init_param_g));
paramg.hwnd = HWND;
paramg.appKey = APP_GUID;
var tmp = (init_param)paramg;
var ret = api_init(ref tmp);//ok