我继承了一个用C语言编写的dll,我从C#中的Windows应用程序(Framework 2.0)访问。最近有些机器已升级到64位Windows 7,并且dll不再在这些机器上返回正确的值。我相信这是因为C函数具有预期为64位的参数类型。
这是C函数的签名
int doFlightCalc_S(double LatA,
double LonA,
double LatB,
double LonB,
int month,
int aircraftCd,
int nbrPsgrs,
int taxiInTm,
int taxiOutTm,
int fuelStopTime,
int *results)
这是从C#
访问函数的定义[DllImport("doFlightCalc.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int doFlightCalc_S(
[MarshalAs(UnmanagedType.R8)] double latA,
[MarshalAs(UnmanagedType.R8)] double lonA,
[MarshalAs(UnmanagedType.R8)] double latB,
[MarshalAs(UnmanagedType.R8)] double lonB,
[MarshalAs(UnmanagedType.I4)] int month,
[MarshalAs(UnmanagedType.I4)] int aircraftCd,
[MarshalAs(UnmanagedType.I4)] int nbrPsgrs,
[MarshalAs(UnmanagedType.I4)] int taxiInTm,
[MarshalAs(UnmanagedType.I4)] int taxiOutTm,
[MarshalAs(UnmanagedType.I4)] int fuelStopTime,
[MarshalAs(UnmanagedType.LPArray)] [Out] int[] results);
如果我将C dll编译为64位dll,同时保留该函数,那么我需要对C#中的函数进行哪些更改?
我会假设我必须将I4更改为I8s但是我会用什么类型替换int和double?以下是:
[MarshalAs(UnmanagedType.R8)] double lonB,
[MarshalAs(UnmanagedType.I4)] int month,
改为:
[MarshalAs(UnmanagedType.R8)] (what would go here?) lonB,
[MarshalAs(UnmanagedType.I8)] long (is long correct here?) month,
还是我在错误的树上吠叫?
答案 0 :(得分:2)
编译64位时,根本不需要进行任何更改。 C和C#版本在32位和64位上相互匹配。
您似乎认为C int在Windows上的64位代码中是8字节宽。它不是。它是4个字节宽。
您可以删除所有MarshalAs属性,因为它们只是重新声明了默认的编组。
从32位操作系统切换到64位操作系统似乎不太可能是造成这种差异的原因。
答案 1 :(得分:1)
根据MSDN页面(http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype.aspx),枚举UnmanagedType.I8
对应于8字节有符号整数,或System.Int64
在C#中别名为long
。我个人的偏好是始终使用结构类型名称Int64
而不是别名,因为它只是让我想到便携式C89中的错误编程,其中long
可能意味着32位或64位整数
类似地,R8
是一个8字节的浮点数。类型System.Double
对应于此成员。
[MarshalAs(UnmanagedType.R8)] Double lonB,
[MarshalAs(UnmanagedType.I8)] Int64 month,
或者这个,取决于你的编码风格偏好
[MarshalAs(UnmanagedType.R8)] double lonB,
[MarshalAs(UnmanagedType.I8)] long month,
然而,我不明白为什么64位会产生影响,除非参数需要一个指针类型(因为这是32位和64位系统之间应该不同的唯一原始类型)。
编辑:忽略我的回答:我没有完全阅读你的问题。如果C函数定义了int
个参数,那么它们将始终保持相同的大小,而不管它所编译的平台的32位或64位性质(假设两个构建使用相同的编译器和操作系统)
答案 2 :(得分:0)
double
仍为double
。在C#double
中是64位实数,R8
是64位实数。 C#中的long
是Int64
,因此也是正确的类型。 I8
是一个64位无符号整数,因为它很长。但是,您没有理由使用I8
,因为C代码中的值都是32位整数(C int == I4 == C#int)。