2013-01-31 7 views
9

Konwertuję stary program Visual BASIC na język C#. Wysyła wiadomości do niektórych maszyn przemysłowych za pośrednictwem sieci Ethernet. W tym celu montuje strumień bajtów z porcji zdefiniowanych przez użytkownika o ustalonych rozmiarach.Jak ustawić typ użytkownika tablicy bajtowej o stałym rozmiarze w języku C#?

Większość z tych fragmentów są małe i C# łatwo stworzyć konstrukcjom kilku bajtów lub wskazówki i kontrolować ich wielkość i układ używając StructLayout użytkownika, na przykład

[StructLayout(LayoutKind.Sequential, Pack = 1)] 

... więc kiedy idziemy do niezarządzane miejsce na kopię bytową, nie mamy kolejności bajtów ani problemów z dopełnieniem.

Ale niektóre ze struktur VB6 są duże tablice, na przykład,

Private Type SEND_MSG_BUFFER_320_BYTES 
    bytes(0 To 319) As Byte '320 bytes 
End Type 

i jestem zmaga się z, jak to zrobić w języku C#. Mogę zrobić stałą tablicę rozmiarze w klasie, np

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public class SOME_BYTES 
    { 
     public byte[] b = new byte[320]; 
    } 

jednak zrobić kopię bajtowy mądry muszę być w stanie odkryć rozmiar w czasie wykonywania i System.Runtime.InteropServices.Marshal. SizeOf zwraca do tego .

Wszelkie sugestie, jak to zrobić, zostaną docenione.

Odpowiedz

7

Myślę, że chcesz zrobić coś takiego:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public class SOME_BYTES 
    { 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst=320)] 
     public byte[] b; 
    } 

byłoby uruchamiasz go w następujący sposób:

Następnie możesz wypełnić plik data.b [] i użyć zestawienia, aby uzyskać dane do wysłania. Atrybut MarshalAs informuje koordynatora, jaki bufor o stałym rozmiarze ma być użyty podczas gromadzenia danych.

Nie musisz używać niebezpiecznego stałego słowa kluczowego, aby robić tego rodzaju rzeczy, i zdecydowanie zalecamy, abyś go unikał.

+0

To działa. Zdecydowanie muszę przeczytać więcej na temat całej gamy usług InteropServices/MarshallAs, ponieważ wygląda na to, że będę pod ich pachami dla tego projektu! – user316117

11

Można użyć tablicę stałym rozmiarze:

unsafe struct SomeBytes { 
    public fixed byte b[320]; 
} 
+1

Cóż, wygląda na to, że działa. Nie byłem zaznajomiony z "niebezpiecznym" słowem kluczowym i odkryłem, że aby go użyć, musisz zbudować z "/ unsafe" dla właściwości kompilacji projektu, co wyłącza sprawdzanie granic i być może inne rzeczy dla całego programu. Jedną rzeczą jest przejście do trybu niebezpiecznego dla kilku metod, które piszę i w pełni rozumiem, ale jestem trochę zaniepokojony ustawieniem "/ unsafe" dla całego programu zawierającego prawie 200 tysięcy linii kodu. Co myślą inni ludzie? – user316117

+4

@ user316117/dangerous nie zmienia niczego w projekcie, z wyjątkiem tego, że umożliwia użycie niebezpiecznego kodu. – ghord

12

Można użyć fixed size buffers jeśli jesteś w porządku z kodem niebezpieczny i zmieniając swoją klasę na struct:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public unsafe struct SomeBytes 
{ 
    public fixed byte MessageData[320]; 
} 

Osobiście będzie spróbuj, aby tego uniknąć, jeśli to możliwe. Jeśli tylko przesyłasz dane przez sieć, dlaczego musisz "wchodzić w przestrzeń niezarządzaną"? Czy potrafisz jakoś usunąć to wymaganie? (Może to fundamentalna - ale to nie wynika z Twojego pytania.)

+0

Istnieje ponad 50 różnych komunikatów, które mogą być wysyłane do maszyny, a każda wiadomość jest montowana w czasie wykonywania z poszczególnych struktur różnych typów.Struktura może mieć podwójny, 16-bitowy uint, kilka bajtów itd. Przechodzenie do niezarządzanej przestrzeni ułatwia wykonanie kopii w pośpiechu. Zobacz moje wcześniejsze pytanie na temat tego http://stackoverflow.com/questions/14485653/copying-different-structs-to-byte-arrays, aby uzyskać więcej szczegółów. – user316117

+0

@ user316117: Robienie bytowej kopii zwykle upraszcza działanie w * krótkim * terminie, ale z mojego doświadczenia bardzo trudno jest migrować do różnych formatów w dłuższej perspektywie. Generalnie wolę bardziej elastyczne podejście do serializacji, np. bufory protokołów. –

+0

Sprawdziłem dokumentację dotyczącą bufora protokołu na https://developers.google.com/protocol-buffers/docs/overview i wygląda na to, że oba końce łącza komunikacyjnego będą musiały wiedzieć o protokole. Sprzęt przemysłowy, z którym rozmawiamy, nie jest komputerem; nie byłoby sposobu zaprogramowania go na akceptację nowego lub innego formatu. Rozmawiałem z kierownictwem, czy kiedykolwiek chcieliby przenieść do nowych lub różnych formatów w przyszłości, a odpowiedź brzmiała jednoznacznie "nie". – user316117

Powiązane problemy