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

时间:2011-04-08 06:45:25

标签: c# .net mono integer unmanaged

我有一个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

如何处理这个可变整数大小但是有一个程序集可以在32位或64位模式下运行.Net或单声道?

2 个答案:

答案 0 :(得分:4)

问题在于64位Windows C长仍然是32位,不像Linux那样是64位,这会引起一些痛苦。

如果您不打算支持64位Windows,则很容易 - 您可以在DllImport定义中将long映射到IntPtr。 32位窗口和linux上的IntPtr都是32位,与长期相同。长64位Linux也是64位,IntPtr也是如此,不过在Windows 64bit上,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

答案 1 :(得分:0)

另一种可能性是使用单个API编写另一个C库,该API不会在.Net平台之间变化,而是为每个API提供正确的包装库。