由于封送问题,无法从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上实现的。

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

非常感谢。

由于封送问题,无法从C#中调用C方法

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

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,然后手动进行编组。