Linux 下 C# Mono P/Invoke .so 动态链接库。
linux 的动态链接库 libgw.so 的函数 如下:
1 struct lbt_chan 2 { 3 uint32_t freq_hz; 4 uint16_t scan_time_us; 5 }; 6 struct lgw_conf_lbt_s 7 { 8 bool enable; 9 int8_t rssi_target; 10 uint8_t nb_channel; 11 struct lbt_chan channels[8]; 12 int8_t rssi_offset; 13 }; 14 15 int board_setconf(struct conf_lbt_s cfg); 16 int board_setconf2(struct conf_lbt_s* cfg);
C#封装如下:
using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public struct lbt_chan { public UInt32 freq_hz; public UInt16 scan_time_us; }; [StructLayout(LayoutKind.Sequential)] public struct conf_lbt_s { [MarshalAs(UnmanagedType.I1)] public bool enable; public sbyte rssi_target; public byte nb_channel; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.Struct)] public lbt_chan[] channels; public sbyte rssi_offset; }; [DllImport(@"libgw.so", EntryPoint = "board_setconf", CallingConvention = CallingConvention.Cdecl)] extern public static Int32 board_setconf(conf_lbt_s cfg); [DllImport(@"libgw.so", EntryPoint = "board_setconf2", CallingConvention = CallingConvention.Cdecl)] extern public static Int32 board_setconf2([MarshalAs(UnmanagedType.LPStruct)]conf_lbt_s cfg);
封装和win环境下一般无二。
这俩函数基本可以总结全部内容了。
特别要注意的是 CallingConvention = CallingConvention.Cdecl
调用约定:
1、Cdecl 调用方清理堆栈。 这使您能够调用具有 varargs 的函数(如 Printf),使之可用于接受可变数目的参数的方法。
2、FastCall 不支持此调用约定。
3、StdCall 被调用方清理堆栈。这是使用平台invoke调用非托管函数的默认约定。
4、ThisCall 第一个参数是 this 指针,它存储在寄存器 ECX 中。 其他参数被推送到堆栈上。 此调用约定用于对从非托管 DLL 导出的类调用方法。
5、Winapi 此成员实际上不是调用约定,而是使用了默认平台调用约定。 例如,在 Windows 上默认为 StdCall,在 Windows CE.NET 上默认为 Cdecl。