我在尝试 PInvoke 第三方 DLL 时发生的 PInvokeStackImbalance 异常故障排除时遇到了困难。根据我在下面的描述,有人可以建议故障排除的后续步骤吗?
我在这里花了一些时间研究与 PInvokeStackImbalance 异常相关的线程,并在 MSDN 上做了一些粗略的阅读。编组和使用非托管代码对我来说仍然相对较新,所以我可能遗漏了一些明显的东西。答案也可能在于第三方 DLL。一个目标是确定我是否应该专注于我的代码或 DLL 以找出问题发生的位置。
我试图通过调用需要一个无符号字符指针的 DLL 来填充托管字节数组。因为我无权访问第三方资源,所以我无法提供一个自包含的示例。我将尝试提供尽可能多的代码来显示错误发生的位置。
第三方标头(C++):
API.h
#define PUCHAR unsigned char *
#define INT32 long
#define UINT32 unsigned long
_declspec( dllexport ) INT32 _stdcall CAPTURE_ReadData(INT32 devID, UINT32 address, UINT32 Num_Bytes,PUCHAR pucBuffer);
_declspec( dllexport ) INT32 _stdcall CAPTURE_ReadStart(INT32 devID, UINT32 start_adr, UINT32 byte_len);
_declspec( dllexport ) INT32 _stdcall CAPTURE_ReadEnd(INT32 devID );
这是我尝试调用这些函数的代码
C#:
namespace CameraTest
{
class CameraInterface : IDisposable
{
// Interface
[DllImport("API.dll")]
public static extern int CAPTURE_ReadStart(int devId, uint startAdr, uint byteLen);
[DllImport("API.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int CAPTURE_ReadData(int devId, uint numBytes,
IntPtr pucBuffer);
[DllImport("API.dll")]
public static extern int CAPTURE_ReadEnd(int devId);
//Code
const int BUFFSIZE = 2592*1944;
private byte[] _buffer = new byte[BUFFSIZE]; // Array to contain image / byte data
const int devId = 0; // Device Id
uint bytesToRead = 2592 * 1944; // Shortcut assignement. Verified other code
// assigns value correctly
const uint startAdr = 0; // Starting address
// Create a pointer that we will later copy its data to the _buffer once
// it has been assigned values.
IntPtr pBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(_buffer[0]*_buffer.Length));
// This function returns successfully with _status = 0
// It initializes the data capture device and specifies how many bytes will be
// read
_status = CAPTURE_ReadStart(devId, startAdr, bytesToRead);
if (_status < 0 ) { // Error handling }
// The ReadData function reads the number of bytes specified from the device
// and assigns the byte array and is supposed to set pBuffer to point to it.
// This ReadData function throws the PInvokeStackImbalance exception.
// If I continue in debug mode, _status gives an error value which indicates
// the primary dll has an issue with communicating with a secondary dll.
// My thought is that the error code has to do with me not specifying the
// correct interface for CAPTURE_ReadData.
_status = CAPTURE_ReadData(devId, bytesToRead, pBuffer);
if (_status < 0 ) { // Error handling }
// Code never reaches this point due to thrown exception
_status = CAPTURE_ReadEnd(devId);
if (_status < 0 ) { // Error handling }
// Marshal pBuffer to _buffer
// IDisposable stuff and freeing allocated items that need it
}
}
我尝试将 ReadData 的调用约定更改为 StdCall,尝试将签名从 IntPtr 更改为 [in,out] byte[] 以及尝试使用 Marshal.UnsafeAddrOfPinnedArrayElement 传递 _buffer 的第一个元素的位置。但是,我不完全确定我是否正确尝试了这些更改,因此我希望向社区学习。
我仍在研究我做错了什么导致异常。我了解我发送的函数调用与调用期望的内容之间存在基本不匹配,但我不完全理解这意味着什么或如何调试或解决该问题。任何人都可以提供的任何指导表示赞赏。如果我遗漏了任何重要信息,请告诉我。