在C#中使用SetFilePointer已经取消了对堆栈的清除



好的,我正在使用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/Invoke:

[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:temptest.txt", text);
var file = File.Open(@"c:temptest.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());

另请注意:

l移动距离[in]

带符号值的低阶32位,用于指定移动文件指针的字节数。如果lpDistanceToMoveHigh不为NULL,则lpDistanceToMoveHigh和lDistanceToMove将形成一个64位带符号值,用于指定要移动的距离。如果lpDistanceToMoveHigh为NULL,则lDistanceToMove是一个32位有符号值。lDistanceToMove的正值将在文件中向前移动文件指针,负值将向后移动文件指针。

lpDistanceToMoveHigh[in,out,optional]

指向要移动的带符号64位距离的高位32位的指针。如果不需要高阶32位,则此指针必须设置为NULL。当不为NULL时,此参数还接收文件指针的新值的高阶DWORD。有关详细信息,请参阅本主题中的"备注"部分。

可能。pinvoke.net允许CallingConvention默认为StdCall(而不是Cdecl设置),因为SetFilePointer被声明为WINAPI(即__StdCall)。不正确的调用约定会损坏堆栈。

最新更新