0

我试图调用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 上。

上面的翻译有什么明显的错误吗?

提前谢谢了。

4

2 回答 2

1

我绝不是编组方面的专家,但我想我会提出一些想法以防万一。

1)尝试IntPtr通过在代码中为它们分配内存来手动编组数组(as)。

2)这条线IntPtr resultPtr = IntPtr.Zero;看起来很可疑。通常,当您从托管代码传递指向非托管代码的指针时,您的工作就是为此指针分配(和释放)内存。查看详情http://msdn.microsoft.com/en-us/library/0szztey7%28v=VS.90%29.aspx

于 2013-07-05T11:53:42.293 回答
0

您的问题出在结构中包含的指针中:

[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并手动进行编组。

于 2013-07-05T12:21:38.273 回答