This is fairly simple struct. You can allocate a byte array, since you know the size and serialize each field manually. Have another method to deserialize.
Thank you for a quick response. I started reading the thread and look up some related samples and documentations. It seems that the process is fairly convoluted and will take a fair amount of computational cycles.
The structure in my post is fairly simplified for example purposes. In the real application, each structure has 16 data fields of 32bit each and there are up to 8 of the structures packed into a data frame in an array. We need to do this 15 to 20 times a second so efficiency is pretty important.
I am now thinking that I might have to do this in RLP since I can do a simple native C structure casting and memory copying operation.
A bit like this… (not an exact code but you get the idea…)
struct DataFrame
{
public byte origin;
public byte num;
public UInt16 ver;
public UInt32 type;
public float field_0;
// more datafields...
public float field_12;
public UInt32 crc;
}
DataFrame[] dataframes;
int32 ptr_frame;
byte[] databuffer;
databuffer = new byte[4096]
dataframes = new DataFrame[8];
ptr_frame = &dataframes;
RLP_fillbuffer(databuffer, ptr_frame, 4096);
Well, except, as you might have already suspected, it pukes at the second from last step where I am trying to get a memory address to the structure array. Since this is a transmit only application, I do not need to be able to go back the other way.
My knowledge of C is a little rusty, but couldn’t you do something like this:
On native side:
int rlpFillBuffer(void *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
struct dataFrame
{
unsigned char origin;
unsigned char num;
unsigned short ver;
unsigned int type;
float field_0;
// more datafields...
}
struct dataFrame *frames = (struct dataFrame*)generalArray;
unsigned char *byteArray = (unsigned char*)args[0];
int bufSize = *(int*)args[1];
// use the frames array to fill the byteArray...
}
On the managed side:
struct DataFrame
{
public byte origin;
public byte num;
public UInt16 ver;
public UInt32 type;
public float field_0;
// more datafields...
public float field_12;
public UInt32 crc;
}
DataFrame[] dataFrames = new DataFrame[8];
byte[] databuffer = new byte[4096]
RLP_FillBuffer.InvokeEx(dataFrames, databuffer, 4096);
Tried it out. The RLP Invoke method causes a runtime error saying parameter 0 is not supported. Presumably, it is choking because it does not know how to cast Dataframe [] to byte [].
This is quite frustrating since I can see in debugger that the I am able to get the 32bit address that is correct. Just that I cannot cast it into form that will be accepted by the managed code methods…
I would imagine there are plenty of others who has ran into this problem when interfacing with external equipments through SPI, UDP, or any data stream that is structured (what data stream isn’t!)
How do others package structured data to transmit over “the wire”?
@ humeno - Are you defining your rlp function like this, with the first parameter as void *generalArray, and calling it with the InvokeEx method? I’ve never tried this, but according to the RLP help file, you should be able to pass your array as the first parameter, and then cast it to whatever you like within the native function.
int rlpFillBuffer(void *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
...
}
You can pass “any array” as long as it is an array of system defined data like Byte, Int, etc. In this case, it is an array of my user defined structure. I am guessing that is what it is choking on.
The key issue here is that I need to pass two arrays to the RLP. I thought I would pass one array plus pointer as a 32bit integer but I am not able to get a pointer to cast to an Int to be able to do that.
@ ianlee74 - Thanks for testing, interesting to know that there’s a difference between the emulator and a real device.
Later I realized that even having a byte pointer does not help much since its still pointing to a managed object. And the internal data structure can’t been seen as a a piece of memory with variables as in unmanaged code.
Sorry, I was suggesting that you test it. I didn’t actually test it today. I have tried this many months ago and it didn’t work. I don’t believe anything has changed that would now allow it to work.