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

本文关键字:整数 处理 | 更新日期: 2023-09-27 17:49:40

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

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

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

我的问题是,在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传递将始终是一个非管理的uint64_t

我怎么能应付这个可变的整数大小,但有一个单一的程序集,将运行在。net或mono在32位或64位模式?

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

问题是,在64位的Windows C上,long仍然是32位的,不像Linux上是64位的,这导致了一点痛苦。

如果你不打算支持64位Windows,这很简单——你可以在DllImport定义中将long映射为IntPtr。IntPtr在32位windows和linux上都是32位的,这与long相同。64位Linux上的Long也是64位的,IntPtr也是64位的,然而在Windows 64位上,当IntPtr是64位的时候,它是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

另一种可能性是编写另一个带有单个API的C库,该API在。net平台之间不变化,而是为每个平台提供正确的包装器库。