gpt4 book ai didi

在 32 位和 64 位 Linux : 中使用 long 的 C# pInvoke

转载 作者:太空狗 更新时间:2023-10-29 12:03:45 30 4
gpt4 key购买 nike

我需要调用 Linux 函数 sysinfo

它的声明是int sysinfo(struct sysinfo *信息);与

直到 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 */
};

这是我目前所拥有的:

调用函数:

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 代码中的“long”是特定于处理器架构的,因为在 x86 32 位 Linux 中,long 的大小是 32 位,而在 x86 64 位 Linux 中,它是 64 位,所以我必须采用 IntPtr,因为它是无符号的,所以我采用 UIntPtr。

然而,在 C#/mono 中,long 始终被定义为 Int64。

现在使用 IntPtr 有点不方便。是否有任何我可以应用的 MarshalAs 属性,或者我可以编写的自定义编码(marshal)拆收器,以便我实际上可以在结构中包含 ulong,但它本地映射到 IntPtr ?这样相同的代码就可以在 x86-32 和 x86-64 上运行。

最佳答案

不,没有任何编码魔法可以解决这个问题。

但是您可以隐藏字段并提供属性访问器:

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
}

关于在 32 位和 64 位 Linux : 中使用 long 的 C# pInvoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23492601/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com