我需要调用Linux函数sysinfo
它的声明是 int sysinfo(struct sysinfo * info); 与
在Linux 2.3.16之前,sysinfo()用于返回以下结构中的信息:
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
char _f[22]; /* Pads structure to 64 bytes */
};
,大小以字节为单位。
自Linux 2.3.23(i386),2.3.48(所有架构)以来,结构是:
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
};
这是我到目前为止所做的:
功能pinvoke:
private const string DoesntFindLibC =@"/lib/x86_64-linux-gnu/libc.so.6";
[System.Runtime.InteropServices.DllImport(DoesntFindLibC)]
private static extern int sysinfo(ref sysinfo_t info);
结构映射:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct sysinfo_t
{
public System.UIntPtr uptime; /* Seconds since boot */
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=3)]
public System.UIntPtr [] loads; /* 1, 5, and 15 minute load averages */
public System.UIntPtr totalram; /* Total usable main memory size */
public System.UIntPtr freeram; /* Available memory size */
public System.UIntPtr sharedram; /* Amount of shared memory */
public System.UIntPtr bufferram; /* Memory used by buffers */
// [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.
public System.UIntPtr totalswap; /* Total swap space size */
public System.UIntPtr freeswap; /* swap space still available */
public ushort procs; /* Number of current processes */
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=22)]
public char[] _f; /* Pads structure to 64 bytes */
}
问题是"长"在C代码中是特定于处理器架构的,因为在x86 32位Linux中,长度为32位,在x86 64位Linux中,它是64位,所以我必须采用IntPtr ,因为它是未签名的,我接受UIntPtr。
在C#/ mono中,long总是定义为Int64。
现在使用IntPtr有点不方便。 是否有我可以应用的MarshalAs属性,或者我可以编写的自定义封送程序,以便我可以在结构中实际拥有ulong,但它本地映射到IntPtr?因此,相同的代码适用于x86-32和x86-64。
答案 0 :(得分:2)
不,你没有任何编组魔法来解决这个问题。
但是,您可以隐藏字段并提供属性访问者:
using System.Runtime.InteropServices;
[StructLayoutAttribute(LayoutKind.Sequential)]
struct sysinfo_t
{
System.UIntPtr _uptime; /* Seconds since boot */
public ulong uptime {
get { return (ulong) _uptime; }
set { _uptime = new UIntPtr (value); }
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
System.UIntPtr [] _loads; /* 1, 5, and 15 minute load averages */
public ulong[] loads {
get { return new ulong [] { (ulong) _loads [0], (ulong) _loads [1], (ulong) _loads [1]) };
set { _loads = new UIntPtr [] { new UIntPtr (value [0]), new UIntPtr (value [1]), new UIntPtr (value [2]) }; }
}
// etc
}
答案 1 :(得分:0)
C'long'类型非常难以编组,因为.NET中没有与所有平台上的大小相匹配的类型。问题是在某些平台(Win32,Win64和Linux32)上C'long'类型可以是4个字节长,同时在其他平台(Linux64)上它可以是8个字节长。在.NET中有'int'类型,无论平台如何都是4字节长,并且有'long'类型,无论平台如何都是8字节长。它们都不能用作C'long'类型和mono documentation suggest to use IntPtr的多平台替代品,正如您已经发现的那样,但我发现这种方法非常不方便(它在Win64上也无法使用!)。因此,我个人更喜欢编组两组不同的函数和结构,一个用'int'NET类型用于C'long'类型为4字节长的平台,另一组用'long'.NET类型为C'long'类型长度为8个字节的平台。然后我只在运行时使用if (IntPtr.Size == 8)
条件来决定应该使用哪个集合。