2016-10-03 6 views
-1

C#에서 발생하는 높은 수준의 문제는 로봇 제어 네트워크 패킷 (Ethercat)을 설명하는 데이터 구조의 단일 복사본을 만든 다음 해당 단일 데이터 구조를 사용하여 패킷 모음에서 데이터를 추출하는 것입니다.다른 유형의 배열을 반환하는 방법은 무엇입니까?

형식을 지정하는 전송 함수 또는 함수를 사용하여 데이터 구조의 암시 적 복제가 있으므로 누적 된 패킷의 데이터를 사용하려고 할 때 문제가 발생합니다. 목표를 설명하는 데 도움이되도록 필자는 내가 원했던 것을 수행하는 파이썬 프로그램을 작성했으며 C#에서이 작업을 수행 할 수 있는지 여부를 결정하는 데 도움을줍니다.

나를위한 C#의 도전은 가변 숫자 형식의 동종 컬렉션을 반환하는 단일 함수 "get_vector"입니다. 이 유형은 패킷 구조에서 정의되며 파이썬에서는 데이터 구조를 다시 정의하지 않고 사용할 수 있습니다.

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

답변