C# ads Twincat Strukturen

Gast #3106580
Lesenswert?

Also habe folgendes Problem.

Sobald ich diese Struktur als Array machen will, kommt immer ein Fehler
1
        public unterstruktur[] unterstruc = new unterstruktur[4];
Wenn ich diese Struktur einfach 4 mal untereinander kopiere und 
deklariere funktioniert es. Wieso nicht mit Array? (Wenn ich die 
SizeConst auf 45 setzte kommt folgender Fehler: 
FatalExecutionEngineError
1
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
2
    public class unterstruktur
3
    {
4
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
5
        public int[] dintArr = new int[4];
6
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
7
        public string stringVal = "";
8
    }
9

10
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
11
    public class GlobalTestType
12
    {
13
        public short intVal;
14
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
15
        public int[] dintArr = new int[4];
16
        [MarshalAs(UnmanagedType.I1)]
17
        public bool boolVal;
18
        public byte byteVal;
19
        public float floatVal;
20
        public double doubleVal;
21
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
22
        public string stringVal = "";
23
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
24
        public unterstruktur[] unterstruc = new unterstruktur[4];
25
    }
#3106638
Lesenswert?

Hallo Peter,

diese Codezeile
1
public unterstruktur[] unterstruc = new unterstruktur[4];
allokiert erst einmal nur den Speicher für das Array mit den 
unterstruktur-Referenzen. Das ist entfernt damit vergleichbar, dass erst 
einmal nur Speicher für sowas wie Pointer allokiert wird. Was noch fehlt 
ist folgendes:
1
for (int index=0; index<4; index++)
2
{
3
    unterstruc[index] = new unterstruktur();
4
}
ABER: Damit ist überhaupt nicht gewährleistet, dass die einzelnen 
unterstruktur-Objekte direkt hintereinander im Speicher liegen, da die 
Runtime die einzelnen Objekte irgendwo im Speicher anlegen kann.

Gruß
Markus
#3106682
Lesenswert?

Was ich noch ergänzen wollte:
DotNet unterscheidet zwischen Referenz-Typen und Value-Typen. Bei 
Referenztypen wird durch die Deklaration einer Variablen lediglich die 
Referenz (eine Art "Pointer") auf das Objekt im Speicher angelegt. Diese 
Referenz kann null sein, also irgendwo ins Nirvana verweisen. Klassen 
(auch die Klasse System.String!) sind IMMER Referenztypen. Im Gegensatz 
dazu wird bei den Valuetypen Speicher für den "Wert" der Variable (ohne 
Indirektion durch eine Referenz) angelegt. Referenztypen sind z.B. int, 
double, also alle skalaren Typen. Aber auch struct-Typen sind 
Value-Typen. Dazu zählen z.B. die (vermeintlichen) "Klassen" 
System.DateTime, System.Guid, ... oder eben selbst definierte 
Struct-Typen. Solche Value-Typen können auch niemals "null" sein.

Wenn Du also anstelle von "class unterstruktur" "struct unterstruktur" 
schreibst, allokierst du mit new unterstruktur[4] 4 unterstruktur 
Elemente und deren Speicher, an einem Stück.

Auch hier ein ABER: Deine "unterstruktur" enthält ein Feld vom Typ 
string. Wie ich oben erwähnt habe, string ist wiederum ein Referenz-Typ. 
Deine unterstruktur enthält anstelle des tatsächloiczhen Strings "nur" 
einen Verweis auf das tatsächliche String-Objekt und nicht etwas 
irgendwelchen Speicher für String-Inhalte.

Hier gibt es noch einen (englischen) Artikel, der das Thema etwas näher 
erläutert: 
http://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types

Gruß
Markus
Gast #3106684
Lesenswert?

Weil ich weiß das bei die daten vom Twincatarray 0 in unterstruc  und 
von 1 in unterstruc1  stehen.
1
    public unterstruktur unterstruc = new unterstruktur();
2
    public unterstruktur unterstruc1 = new unterstruktur();

aber auch die for initialisierung funktioniert nicht. es wird ja auch 
kein fehler bei der initialisierung angezeigt...
#3106794
Lesenswert?

Markus Volz schrieb:
> ABER: Damit ist überhaupt nicht gewährleistet, dass die einzelnen
> unterstruktur-Objekte direkt hintereinander im Speicher liegen, da die
> Runtime die einzelnen Objekte irgendwo im Speicher anlegen kann.

Einfach mal ausprobieren...
1
// C/C++ in einer nativen Win32-DLL
2
#pragma pack(4)
3
struct SubStruct {
4
  double a;
5
  float b;
6
};
7
#pragma pack(4)
8
struct TestStruct {
9
  int c;
10
  unsigned char d;
11
  SubStruct e[4];
12
};
13

14
extern "C" {
15
  WIN32PROJECT1_API double _cdecl fnWin32Project1(TestStruct* tp)
16
  {
17
    return tp->e[2].a;
18
  }
19
}
20

21
und in C#
22

23
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
24
    public struct SubStruct {
25
      public double a;
26
        public float b;
27
    };
28

29
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
30
    public struct TestStruct {
31
        public int c;
32
        public byte d;
33
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
34
        public SubStruct[] e;
35
    };
36

37
        [DllImport(@"Win32Project1.dll", EntryPoint = "fnWin32Project1", CallingConvention = CallingConvention.Cdecl)]
38
        public static extern double fnWin32Project1(ref TestStruct tp);
39

40
        void TestCall() {     
41
            TestStruct ac = new TestStruct();
42
            ac.e = new SubStruct[4];
43
            ac.e[2].a = 12345.6;
44
            double res = fnWin32Project1(ref ac);
45
            return res;
46
        }
Gast #3107149
Lesenswert?

@Arc Net
Arc Net schrieb:
>> ABER: Damit ist überhaupt nicht gewährleistet, dass die einzelnen
>> unterstruktur-Objekte direkt hintereinander im Speicher liegen, da die
>> Runtime die einzelnen Objekte irgendwo im Speicher anlegen kann.
Wenn Du meine ersten beiden Posts etwas genauer gelesen hättest ;-), 
wäre Dir wahrscheinlich aufgefallen, dass das von Dir zitierte ABER sich 
auf Klassen (class) bezieht. Dein Beispiel verwendet struct. Dazu habe 
ich in meinem 2. Post was geschrieben. :-)

Gruß
Markus
Gast #3114756
Lesenswert?

Klar gibts da was. Schau Dir mal die Klasse System.Text.ASCIIEncoding 
an. 
http://msdn.microsoft.com/en-us/library/system.text.asciiencoding.aspx

Neben ASCIIEncoding gibt es im Namespace auch noch UnicodeEncoding, 
UTF32Encoding, UTF7Encoding und UTF8Encoding. Wie die Klassen verwendet 
werden, findest Du in einem Beispiel unter dem obigen Link.

Gruß
Markus

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren