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。