c# - 处理不同的非托管整数大小

标签 c# .net mono integer unmanaged

我有一个 C 库。它有许多函数调用,如下所示:

void init_foo( unsigned long x, unsigned long y );

库本身在运行时动态加载(更像是一个插件)。 header 在所有平台上都是一致的。

我的问题是在 windows 和 32 位 linux 上,unsigned long 是 32 位,而在 64 位 linux 上是 64 位。

这个库的各种实现都接受这一点,你需要为正确的目标平台构建你的 C 程序(如预期的那样)。

根据架构,我的互操作方法需要是其中之一。

#if lin64
[DllImport("libfoo")]
public static void init_foo( Uint64 x, Uint64 y );
#else
[DllImport("libfoo")]
public static void init_foo( Uint32 x, Uint32 y );
#endif

我可以使用的 C# 类型在所有平台上都是固定大小的(它们应该是这样)。因此,我从 .Net/Mono 传递的托管 long 将始终是非托管 uint64_t

我如何处理这个可变的整数大小,同时拥有一个可以在 .Net 或单声道上以 32 位或 64 位模式运行的程序集?

最佳答案

问题在于,在 64 位 Windows 上,C long 仍然是 32 位,而在 Linux 上它是 64 位,这会导致一些痛苦。

如果您不打算支持 64 位 Windows,这很容易 - 您可以在 DllImport 定义中将 long 映射到 IntPtr。 IntPtr在32bit的windows和linux上都是32bit的,和long一样。 Long 在 64 位 Linux 上也是 64 位,IntPtr 也是 64 位,但是在 Windows 64 位上 IntPtr 是 64 位,而 long 是 32 位。

如果您想支持 64 位 Windows,您可以同时定义两个签名 - 一个用于 64 位,一个用于 32 位:

[DllImport("libfoo", EntryPoint="init_foo")]
public static void init_foo_64bit( Uint64 x, Uint64 y );

[DllImport("libfoo", EntryPoint="init_foo")]
public static void init_foo_32bit( Uint32 x, Uint32 y );

然后在您的代码中,您可以在运行时动态决定调用哪一个:

public void InvokeFoo(long x, long y)
{
    if (Environment.Is64BitProcess)
        return init_foo_64bit(x, y);
    return init_foo_32bit((int)x, (int)y);
}

P.S:如果您不在 .NET 4 上,另一种检查您是否是 64 位进程的方法是 bool is64Bit = IntPtr.Size == 8

关于c# - 处理不同的非托管整数大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5591421/

相关文章:

c# - EntityFramework 外键作为具有流畅 API 的主键

c# - Parallel for each 循环不保存所有文件

c# - Windows Phone 在应用程序恢复时运行代码

asp.net - 您可以使用 Mono Develop 直观地编辑 asp.net 项目的 html/view 部分吗?

asp.net-mvc - Mono 2.10 附带哪个版本的 ASP.NET MVC?

c# - StackExchange.Redis 无法与 Mac OS X 中的 Mono 连接

c# - RabbitMQ.Client.Exceptions.OperationInterruptedException

c# - 需要一些关于尝试模拟 .NET WebClient 或等效物的建议

c# - 在不调用 Count 的情况下检查 List<T> 是否有任何值?

c# - LINQ 除了没有按预期工作