簡體   English   中英

由於封送問題,無法從C#p /調用C方法

[英]Cannot p/invoke C method from C# due to marshalling issues

我正在嘗試調用下面的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上。

上述翻譯有明顯的問題嗎?

提前謝謝了。

我絕不是Marshaling的專家,但我想我會提出一些想法以防萬一。

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 marshaller編組指向嵌入在結構內部的數組的指針。 這種編組形式僅適用於功能參數。

您需要將這兩個字段都聲明為IntPtr並手動進行編組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM