0

I'm trying to call a C++ dll function in C#. The function has a struct as a parameter and I have a problem with the variable aby_data[8]. I defined the unsigned char[] as a byte[], the program doesn't crash but I don't receive any data.

Struct C++

typedef struct st_canmsg
{
    long l_id;
    unsigned char by_len;
    unsigned char by_msg_lost;
    unsigned char by_extended;
    unsigned char by_remote;
    unsigned char aby_data[8];
    unsigned long ul_tstamp;
} CMSG;

Conversion to C#

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CMSG
{
    public Int32 l_id;
    public byte by_len;
    public byte by_msg_lost;
    public byte by_extended;
    public byte by_remote;
    public byte aby_data[];
    public UInt32 ul_tstamp;
};

CMSG t_CANMsg[] = new CMSG[1];
t_CANMsg[0].aby_data = new byte[8];
t_CANMsg[0].aby_data[0] = 01;
t_CANMsg[0].aby_data[1] = 02;
t_CANMsg[0].aby_data[2] = 03;
t_CANMsg[0].aby_data[3] = 04;
t_CANMsg[0].aby_data[4] = 05;
t_CANMsg[0].aby_data[5] = 06;
t_CANMsg[0].aby_data[6] = 07;
t_CANMsg[0].aby_data[7] = 08;

l_retval = canSend(handle, out t_CANMsg[0], out len);
1
  • You need to apply [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] to the aby_data member. Do note that out is weird, surely needs to be ref when you initialize the structure before the call. Maybe [In, Out] as well. Commented Nov 14, 2017 at 0:04

2 Answers 2

1

You're marshalling a fixed-length array, but you did not specify the size of your array in your struct definition.

Can you try to update your struct definition like this:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CMSG
{
    public Int32 l_id;
    public byte by_len;
    public byte by_msg_lost;
    public byte by_extended;
    public byte by_remote;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte aby_data[];
    public UInt32 ul_tstamp;
};

Alternatively, you can also try to explicitly define the bytes:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CMSG
{
    public Int32 l_id;
    public byte by_len;
    public byte by_msg_lost;
    public byte by_extended;
    public byte by_remote;
    public byte aby_data_0;
    public byte aby_data_1;
    public byte aby_data_2;
    public byte aby_data_3;
    public byte aby_data_4;
    public byte aby_data_5;
    public byte aby_data_6;
    public byte aby_data_7;
    public UInt32 ul_tstamp;
};

If you're still having issues, you also share the declaration of canSend?

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Frederik Carlier the second option works fine!
0

Based on the Frederik Carlier code I got this solution for use it as array:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CMSG
{
    public Int32 l_id;
    public byte by_len;
    public byte by_msg_lost;
    public byte by_extended;
    public byte by_remote;
    public byte aby_data_0;
    public byte aby_data_1;
    public byte aby_data_2;
    public byte aby_data_3;
    public byte aby_data_4;
    public byte aby_data_5;
    public byte aby_data_6;
    public byte aby_data_7;
    public UInt32 ul_tstamp;

    public byte[] aby_data(){
        byte[] aby_data_array = new byte[8];
        aby_data_array[0] = aby_data_0;
        aby_data_array[1] = aby_data_1;
        aby_data_array[2] = aby_data_2;
        aby_data_array[3] = aby_data_3;
        aby_data_array[4] = aby_data_4;
        aby_data_array[5] = aby_data_5;
        aby_data_array[6] = aby_data_6;
        aby_data_array[7] = aby_data_7;
        return aby_data_array;
    }
};


l_retval = canRead(handle, out t_CANMsg[0], out len);
byte data [] = t_CANMsg[0].aby_data();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.