Autor Beitrag
Codeexplorer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 39



BeitragVerfasst: Fr 27.07.07 13:09 
Hallo zusammen,
ich möchte mit einer externen Hardware über USB eine Reihe von Telegrammen austauschen. Die Daten lese und schreibe ich über eine DLL als Byte-Array. Den Aufbau Telegramme habe ich als struct-Typen in meinem Code hinterlegt. Die Strukturen sind sehr unterschiedlich aufgebaut: Sie haben unterschiedliche Anzahl von Elementvariablen, unterschiedlich lange Elementvariablen etc..
Da es eine ganze Menge Telegramme sind, möchte ich beim Umkopieren nicht jede Elementvariable einzeln anfassen müssen, sondern würde das ganze gerne im Block umkopieren können (struct in array und umgekehrt).
Ich habe mir schon mal die Klassen Bitconverter und Marshal angeschaut, bin da aber nicht so richtig fündig geworden. Weiß da jemand eine elegante Möglichkeit oder muß ich jetzt einfach tiefer in das Thema "unmanaged code" einsteigen ?
Grüße
Oliver


Zuletzt bearbeitet von Codeexplorer am Mo 30.07.07 13:00, insgesamt 1-mal bearbeitet
Codeexplorer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 39



BeitragVerfasst: Mo 30.07.07 10:10 
Titel: Zwischenstand
Ein Dankeschön an vinh2b und Codeproject.
Der Code unten ist zwar noch nicht getestet, aber so ähnlich könnte es gehen.
Unschön ist aber noch, dass man die Größe des Byte-Arrays im zugehörigen Attribut
hart codieren muss.
Außerdem muss ich für jedes Telegramm eine eigene Methode setTelStructureByArr
und setArrayByStructure anlegen. - Eine Menge kopierter Code. Hmm, hmmm ...

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
[StructLayout(LayoutKind.Sequential)]
public struct TelInitData
{
    public byte telNr;
    public byte slavesCnt1;
    public byte slavesCnt2;
}

public class InitTel
{
    // 3 bytes struct
    private TelInitData data;
    // 3 bytes array
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    private byte[] telInitArray;
    
    public Init()
    {
        telinitArray = new byte[3];
    }

    public void setTelStructureByArr(byte[] arr)
    {
        IntPtr ptData = Marshal.AllocHGlobal(3);
        Marshal.Copy(arr, 0, ptData, 3);
        data = (TelInitData)Marshal.PtrToStructure(ptData, typeof(TelInitData));
        Marshal.FreeHGlobal(ptData);
    }

    public void setArrayByStructure(TelInitData dataStruc)
    {
        IntPtr ptData = Marshal.AllocHGlobal(3);
        Marshal.StructureToPtr(data, ptData, true);
        Marshal.Copy(ptData, telInitArray, 03);
        Marshal.FreeHGlobal(ptData );
    }
}


Zuletzt bearbeitet von Codeexplorer am Mo 30.07.07 12:57, insgesamt 1-mal bearbeitet
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 30.07.07 12:07 
Wenn du die Daten sowieso an eine unmanaged Dll übergibts, wozu benötigst du dann überhaupt das managed Array? Genügt dir nicht einfach der Pointer?
Codeexplorer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 39



BeitragVerfasst: Mo 30.07.07 12:44 
Guter Hinweis - da werde ich 'mal 'drüber nachdenken.
Der Beispielcode den ich nutze, benutzt eine managed DLL, die wiederum
auf eine unmanaged DLL zugreift. Vielleicht sollte ich gleich die
Original(unmanaged)-Dll ohne Umwege verwenden ...
PS: In diesem Zusammenhang war:
ausblenden C#-Quelltext
1:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]					

wahrscheinlich sogar unnötig. Das kommt vom vielen Abkupfern und wenig
denken. :wink:

Nachtrag: Nochmal Danke für den Hinweis. Ich werde nun wohl doch die
unmanaged DLL direkt verwenden. Das ist zwar ein bisschen aufwändiger,
aber dafür lernt man mehr dabei ...