好吧,我正在使用C#的SetFilePointer函数与.NET 4.0。 下面是我用来调用这个函数的dllimports:
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
static extern uint SetFilePointer([In] SafeFileHandle hFile, [In] long lDistanceToMove, [Out] out int lpDistanceToMoveHigh, [In] EMoveMethod dwMoveMethod);
每当我运行使用SetFilePointer函数在调试器中的代码,我得到这个异常:
PInvokeStackImbalance was detected Message: A call to PInvoke function 'MyDiskStuff!MyDiskStuff.HardDisk::SetFilePointer' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
每当我在调试器外运行相同的代码,我不明白上面的例外。
下面是我使用做出SetFilePointer调用的代码:
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
uint retvalUint = SetFilePointer(mySafeFileHandle, myLong, out myInt, EMoveMethod.Begin);
是不是有什么毛病我dllimport的签名?
您的P / Invoke签名是有点过:
下面是Win32的定义:
DWORD WINAPI SetFilePointer(
_In_ HANDLE hFile,
_In_ LONG lDistanceToMove,
_Inout_opt_ PLONG lpDistanceToMoveHigh,
_In_ DWORD dwMoveMethod
);
在这里,与你指定的枚举P /调用:
[DllImport("kernel32.dll", EntryPoint="SetFilePointer")]
static extern uint SetFilePointer(
[In] Microsoft.Win32.SafeHandles.SafeFileHandle hFile,
[In] int lDistanceToMove,
[In, Out] ref int lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod) ;
编辑:哦,还有一些测试代码:
var text = "Here is some text to put in the test file";
File.WriteAllText(@"c:\temp\test.txt", text);
var file = File.Open(@"c:\temp\test.txt", FileMode.OpenOrCreate);
int moveDistance = 10;
int moveDistanceHighBits = 0;
uint retvalUint = SetFilePointer(file.SafeFileHandle, moveDistance, ref moveDistanceHighBits, EMoveMethod.Begin);
Debug.Assert(Encoding.ASCII.GetBytes(text)[moveDistance] == file.ReadByte());
从文档还要注意:
lDistanceToMove [IN]
低阶32位带符号的值,它指定移动的文件指针的字节数的。 如果lpDistanceToMoveHigh不是NULL,lpDistanceToMoveHigh和lDistanceToMove形成单个64位有符号值,它指定移动的距离。 如果lpDistanceToMoveHigh为NULL,lDistanceToMove是一个32位有符号值。 对于lDistanceToMove正值向前移动文件指针在文件中,而负值移动文件指针回。
lpDistanceToMoveHigh [IN,OUT,可选]
的指针符号的64位距离的高阶32位移动。 如果你不需要高阶32位,这个指针必须设置为NULL。 当不为NULL,该参数还接收文件指针的新值的高位DWORD。 欲了解更多信息,请参阅本主题中的注释部分。
有可能。 pinvoke.net让CallingConvention默认STDCALL(而不是你的cdecl设置),并自SetFilePointer被声明为WINAPI(这是__stdcall)。 不正确的调用约定会损害你的筹码。