C#では、ロボット制御ネットワークパケット(Ethercat)を記述するデータ構造の単一コピーを作成し、その単一データ構造を使用してパケットの集合からデータを抽出することが、高度な問題です。異なる種類の配列を返す方法は?
型を指定するキャストまたは呼び出し関数でデータ構造の暗黙の重複があるため、蓄積されたパケットからデータを使用しようとすると問題が発生します。目標を説明するのを助けるために、私はPythonプログラムを書いています。これは、私が望むことを実行し、C#でこれを行うことが可能かどうかを判断するのに役立ちます。
C#での私の挑戦は、可変数値型の同種のコレクションを返す単一の関数 "get_vector"です。この型はパケット構造体で定義され、Pythonではデータ構造の再定義を定義せずに使用できます。
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
私はこの質問を作成するのに多くの時間を費やし、問題解決のために数十時間を費やしました。私には、C#の根本的な問題(またはそれについての私の理解)に触れるようです。これが明らかに悪い質問であれば、私は否定的に投票されました。それは私がなぜそう思うか分かりません。 – pathfinder