1、最近做项目遇到,C#调用C++dll里的函数需要传递结构体参数,发现这个并不是简单的在C#里定义相应的结构体就可以的,下面以一个例子来说明解决的办法,C++中的函数和结构体如下:
uint msec_set_igr_gen_cfg(int port, IGR_GEN_T *igr_gen)
{
return 0;
}
typedef struct {
int aa_disable; /*/< authentiation adjust checking disable */
int badtag_rej; /*/< reject packet if it is bypassed due to badtag */
int pad_en; /*/< pad non-rejected packets up to 64B */
int byp_ctl_sl; /*/< bypass packet if SL field does not correspond to packet len */
int byp_ctl_v; /*/< bypass packet if V bit is set */
int byp_ctl_sc; /*/< bypass packet if SC bit and either ES or SCB bits are set */
int byp_ctl_ec; /*/< bypass packet if DC bits are not 00 or 11 */
int sectag_flag; /*/< select which flag bit indicates that a SEC tag was present in pkt */
} IGR_GEN_T;
在C#中 首先需要使用Dllimport将相应的C++dll load进来,然后定义相应的结构体,具体如下:
[DllImport("..\\debug\\mgd_MacSec.dll")]
private static extern UInt32 msec_set_igr_gen_cfg(int port, IntPtr igr_gen);
结构体定义:
[StructLayout(LayoutKind.Sequential)]
public class IGR_GEN_T
{
int aa_disable; /*/< authentiation adjust checking disable */
int badtag_rej; /*/< reject packet if it is bypassed due to badtag */
int pad_en; /*/< pad non-rejected packets up to 64B */
int byp_ctl_sl; /*/< bypass packet if SL field does not correspond to packet len */
int byp_ctl_v; /*/< bypass packet if V bit is set */
int byp_ctl_sc; /*/< bypass packet if SC bit and either ES or SCB bits are set */
int byp_ctl_ec; /*/< bypass packet if DC bits are not 00 or 11 */
int sectag_flag; /*/< select which flag bit indicates that a SEC tag was present in pkt */
public IGR_GEN_T()
{
aa_disable = 0;
badtag_rej = 0;
pad_en = 0;
byp_ctl_ec = 0;
byp_ctl_sc = 0;
byp_ctl_sl = 0;
byp_ctl_v = 0;
sectag_flag = 0;
}
} ;
在代码中具体引用函数时如下所示,
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(igr_gen));
Marshal.StructureToPtr(igr_gen, ptr, false);
UInt32 ret = _msec_set_igr_gen_cfg(port, ptr);
igr_gen = (IGR_GEN_T)Marshal.PtrToStructure(ptr, typeof(IGR_GEN_T));
Marshal.FreeHGlobal(ptr);
return ret;
从以上步骤可以看出,结构体参数的传递需要marshal做辅助做相应的转化,以intptr的方式传输结构体参数。