由于封送问题,无法从C#中调用C方法
本文关键字:调用 方法 于封送 问题 | 更新日期: 2023-09-27 18:21:13
我正在尝试调用下面的I2CTransfer
函数,并立即获得一个System.NotSupportedException
。我怀疑我的编组是错误的,但无法解决问题。
以下是C结构:
BOOL I2CTransfer(HANDLE hDev, PI2C_TRANSFER_BLOCK pI2CTransferBlock);
typedef struct {
I2C_PACKET *pI2CPackets;
INT32 iNumPackets;
} I2C_TRANSFER_BLOCK, *PI2C_TRANSFER_BLOCK;
typedef struct {
BYTE byAddr;
BYTE byRW;
PBYTE pbyBuf;
WORD wLen;
LPINT lpiResult;
} I2C_PACKET, *PI2C_PACKET;
下面是我正在尝试的c#结构:
[DllImport("i2csdk.dll", EntryPoint = "I2CTransfer")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool I2CTransfer(IntPtr hI2C,ref I2C_TRANSFER_BLOCK pI2CTransferBlock);
[StructLayout(LayoutKind.Sequential)]
public struct I2C_TRANSFER_BLOCK
{
public I2C_PACKET[] pI2CPackets;
public int iNumPackets;
}
[StructLayout(LayoutKind.Sequential)]
public struct I2C_PACKET
{
public byte byAddr;
public byte byRW;
public byte[] pbyBuf;
public UInt16 wLen;
public IntPtr lpiResult;
}
呼叫代码:
I2C_TRANSFER_BLOCK i2CTransferBlock = new I2C_TRANSFER_BLOCK();
I2C_PACKET packet = new I2C_PACKET();
int result;
IntPtr resultPtr = IntPtr.Zero;
//Populating data...
byte[] pBuf = new byte[1 + pbData.Length];
pBuf[0] = (byte) ((regStart & 0x7F) << 1);
Array.Copy(pbData, 0, pBuf, 1, pbData.Length);
// Fill packet for register write
packet.pbyBuf = pBuf;
packet.wLen = (ushort) pBuf.Length;
packet.byRW = NativeConstants.I2C_RW_WRITE;
packet.byAddr = address;
packet.lpiResult = resultPtr;
// Fill transfer block
i2CTransferBlock.pI2CPackets = new I2C_PACKET[] {packet};
i2CTransferBlock.iNumPackets = 1;
// NotSupportedException here
bool brc = I2CTransfer(port, ref i2CTransferBlock);
在调用该方法之前,数组将在C#中初始化。
我已尝试添加[MarshalAs(UnmanagedType.LPArray)]
到阵列(pI2cPackets和pbyBuf)都没有用。
这是在Windows CE压缩框架.NET 3.5上实现的。
上面的翻译有什么明显的错误吗?
非常感谢。
我不是编组方面的专家,但我想我会提出一些想法以防万一。
1) 尝试通过在代码中为数组分配内存来手动封送数组(作为IntPtr
)。
2) 这条线路IntPtr resultPtr = IntPtr.Zero;
看起来可疑。通常,当您将指针从托管代码传递到非托管代码时,您的工作是为该指针分配(和释放)内存。查看此以了解详细信息http://msdn.microsoft.com/en-us/library/0szztey7%28v=VS.90%29.aspx
您的问题在于结构中包含的指针:
[StructLayout(LayoutKind.Sequential)]
public struct I2C_TRANSFER_BLOCK
{
public I2C_PACKET[] pI2CPackets; // here ....
public int iNumPackets;
}
[StructLayout(LayoutKind.Sequential)]
public struct I2C_PACKET
{
public byte byAddr;
public byte byRW;
public byte[] pbyBuf; // .... and here
public UInt16 wLen;
public IntPtr lpiResult;
}
您无法说服p/invoke封送器封送指向嵌入结构中的数组的指针。这种编组形式仅适用于函数参数。
您需要将这两个字段都声明为IntPtr
,然后手动进行编组。