Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
由于编组问题,无法从C#p/调用C方法_C#_Interop_Compact Framework_Pinvoke - Fatal编程技术网

由于编组问题,无法从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%拥有所有权。如果它指向自己的数据,并且数据被钉住,那么这会消除这种担心吗?