pathfinder pathfinder - 1 month ago 14
C# Question

How to return different types of arrays?

The high level problem I'm having in C# is to make a single copy of a data structure that describes a robot control network packet (Ethercat), and then to use that single data structure to extract data from a collection of packets.

The problem arises when attempting to use the data from the accumulated packets as there is implicit duplication of the data structure with casting or calling functions that specify the type. To assist in explaining the goal, I've written a python program that does what I want and would like help to determine if its possible to do this in C#.

The challenge for me in C# is the single function "get_vector" which returns a homogeneous collection of a variable numerical type. This type is defined in the packet structure and in python can be used without defining re-defining the data structure.

import struct

# description of the complete packet
class PACKET_STRUCTURE :

# given a field name and a list of packets, return a vector
# this is the function that seems impossible in C# because the type of what is returned changes
def get_vector(self, name, packet_list):
# locate the packet definition by the name of the vector
result = [x for x in self.packet_def if x.field_name == name]

# without error checking, pos contains the location of the definition
pos = result[0].position;

# decode ALL the pacckets in the (encoded) packet list - returning a list of [time_sec, status, position
# in C# this step is similar to using Marshal.PtrToStructure to transform from byte[] to a struct
decoded_packet_list = [struct.unpack(self.fmt_str, packet) for packet in packet_list];

# from the list of decoded_packets, extract the desired field into its own list
vector = [decode[pos] for decode in decoded_packet_list]

# in C# this is similar to:
# var CS_vector = decode_packet_list.Select(item => item.field_name).ToArray();
# so far in C# there is no duplication of the packet structure.
# but after this point, assume I cast CS_vector to object and return it -
# to use the object, I've not figured out how to avoid casting it to some type of array
# eg double[], int32[]
return vector

def __init__(self):
self.packet_def = list();
self.fmt_str = "<";
self.cnt = 0;

# add description of single item to the structure
def add(self, struct_def) :
struct_def.position = len(self.packet_def);
self.packet_def.append(struct_def);
self.fmt_str += struct_def.type;

# create a simple packet based on a counter based on the defined structure
def make_packet(self):
vals = [self.cnt*10+x for x in range(0, len(self.packet_def))];
self.cnt += 1;
pk = apply(struct.pack, [self.fmt_str] + vals)
# print len(pk), ["%c" % x for x in pk]
return pk

def get_names(self):
return [packet_items.field_name for packet_items in self.packet_def];


# the description of a single field within the packet
class PACKET_ITEM :
def __init__(self, field_name, type):
self.field_name = field_name
self.type = type;
# self.offset = 0;
self.position = 0;


if __name__ == "__main__" :

INT32 = "l";
UINT16 = "H";
FLOAT = "f";

packet_def = PACKET_STRUCTURE();

# create an example packet structure - which is arbituary and could be anything - it could even be read from a file
# this definition is the ONLY defintion of the packet structure
# changes here require NO changes elsewhere in the program
packet_def.add(PACKET_ITEM("time_sec", FLOAT))
packet_def.add(PACKET_ITEM ("status",UINT16))
packet_def.add(PACKET_ITEM ("position",INT32))

# create a list of packets
pk_list = list()
for cnt in range(0,10) :
pk_list.append(packet_def.make_packet());

################################
# get the vectors without replicating the structure
# eg no int32[] position = (int32[])get_vector()

name_list = packet_def.get_names();
for name in name_list :
vector = packet_def.get_vector(name, pk_list);
print name, vector

Answer

The answer is to store the arrays in a collection of type List<dynamic>

The return type of function that returns elements from the collection should also be dynamic.

Here is the more complete answer to my miss-understood question which this one attempted to clarify.

Comments