由于编组问题,无法从C#p/调用C方法
我试图调用下面的由于编组问题,无法从C#p/调用C方法,c#,interop,compact-framework,pinvoke,C#,Interop,Compact Framework,Pinvoke,我试图调用下面的I2CTransfer函数,并立即得到一个系统。NotSupportedException。我怀疑我的编组是错误的,但无法解决问题 以下是C结构: BOOL I2CTransfer(HANDLE hDev, PI2C_TRANSFER_BLOCK pI2CTransferBlock); typedef struct { I2C_PACKET *pI2CPackets; INT32 iNumPackets; } I2C_TRANSFER_BLOCK, *PI2
I2CTransfer
函数,并立即得到一个系统。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);
I2C_传输_块i2CTransferBlock=新I2C_传输_块();
I2C_数据包=新的I2C_数据包();
int结果;
IntPtr resultpttr=IntPtr.Zero;
//正在填充数据。。。
字节[]pBuf=新字节[1+pbData.Length];
pBuf[0]=(byte)((regStart&0x7F)我绝对不是封送处理方面的专家,但我想我会提供一些想法以防万一
1) 通过在代码中为数组分配内存,尝试手动封送数组(如IntPtr
)
2) 此行IntPtr resultpttr=IntPtr.Zero代码>看起来可疑。通常,当您从托管代码传递指向非托管代码的指针时,您的工作是为此指针分配(并释放)内存。查看此项了解详细信息您的问题在结构中包含的指针中:
[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
,并手动进行编组。请显示用于实例化这些结构并调用方法的代码。您的用户名让我感到困惑:)完成。我就是这么做的。我潜伏在StackOverflow周围,盗取别人的名字。用于.NETCF的pinvoke封送员有很多限制。您可能需要将该数组声明为IntPtr,并使用GCHandle.Alloc()+addrofpindedObject()自行封送该数组。电话会议是另一个,你忽略了它。仅支持_stdcall,您必须在本机代码中以这种方式声明它。使用@Hans Passant提到的IntPtr和GCHandle.Alloc()+addrofPindeObject()完成了此操作-谢谢。LPArray
用于参数,不能在结构成员上使用。请务必小心处理lpiResult。它应该指向哪里?它是否指向I2C库代码?它是否指向您自己的数据?如果它指向您自己的数据,调用是否同步?如果是这样,那太好了。否则,如果将它指向托管对象中包含的某个对象,您将陷入痛苦的境地。如果您完全清楚动态分配内存的所有权和使用寿命等,那就太好了。如果没有,请考虑编写C适配器以使C 100%拥有所有权。如果它指向自己的数据,并且数据被钉住,那么这会消除这种担心吗?