Can't p / call C method from C # due to sorting problems

I am trying to call the function I2CTransfer

below and I get it right away System.NotSupportedException

. I suspect my marshalling is wrong but can't fix the problem.


Here are the C structures:

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;

      


And here are the C # structures I am trying to make:

[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;
}

      


Call code:

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);

      


Arrays are initialized in C # before calling the method.

I tried adding   [MarshalAs(UnmanagedType.LPArray)]

for arrays (pI2cPackets and pbyBuf) to no avail.

This is in Windows CE - a compact .NET 3.5 framework.

Is there something clearly wrong with the above translation?

Thank you very much in advance.

0


source to share


2 answers


Your problems are in the pointers contained in structs:

[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;
}

      



You cannot convince the p / invoke marshaler to marshal pointers to arrays embedded inside structs. This sorting form is available only for function parameters.

You need to declare both of these fields as IntPtr

and do the sort manually.

0


source


I'm by no means a marshaling expert, but I think I'll jot down a few ideas just in case.

1) try manually marshaling the arrays (how IntPtr

) by allocating memory for them in your code.



2) This line IntPtr resultPtr = IntPtr.Zero;

looks suspicious. Typically, when you pass a pointer to unmanaged code from managed code, your job allocates (and frees) memory for that pointer. See http://msdn.microsoft.com/en-us/library/0szztey7%28v=VS.90%29.aspx for details

+1


source







All Articles