2016-10-03 13 views
-1

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 
+0

私はこの質問を作成するのに多くの時間を費やし、問題解決のために数十時間を費やしました。私には、C#の根本的な問題(またはそれについての私の理解)に触れるようです。これが明らかに悪い質問であれば、私は否定的に投票されました。それは私がなぜそう思うか分かりません。 – pathfinder

答えて

0

答えは、コレクションから要素を返す関数の戻り型は、動的でなければならないタイプのコレクション内の配列を格納するList<dynamic>

あります。

ここにはmore complete answerから私のmiss-understood questionまでですが、これを明確にしようとしています。

関連する問題