Types in Types Inline?

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Der Eisvogel

Betreff: Types in Types Inline?

BeitragSa, Jun 25, 2011 15:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo

Bisher bin ich immer davon ausgegangen, dass Types in Types per Pointer referenziert werden. Jedoch hab ich heute was anderes festgestellt.

BlitzMax: [AUSKLAPPEN]
Type T1
Field a:T2
Field b:T2
End Type

Type T2
Field c:Int
Field d:Int
End Type


Bisher war es für mich immer so, dass die Felder a und b einen Pointer auf Instanzen von T2 beinhalten, somit T1 exact 8 Byte lang ist. Heutige Tests haben ergeben, dass T1 aber in wirklichkeit 16 Byte lang ist, da die beiden Instanzen von T2 als Inline Objekte in T1 eingebunden werden, so dass der Type imaginär so aussieht:
BlitzMax: [AUSKLAPPEN]
Type T1
Field c:Int
Field d:Int
Field c:Int
Field d:Int
End Type


Hatte ich hier nur etwas verwechselt und das ist völlig normal, oder ist da noch was anderes, was eine Rolle spielt bzw. wusstet ihr das auch schon?

Leider hat mir dieses Verhalten von BlitzMax heute den Kopf explodieren lassen in Kommunikation mit der WinAPI, die ja manchmal genau das Verhalten verlangt, jedoch auch manchmal ein andere bevorzugt. So z.B.: Eine Struktur die einen weiteren Verweis auf eine RECT-Struktur beinhalten könnte man in BlitzMax folglich auch so bauen:
BlitzMax: [AUSKLAPPEN]
Type Structur
Field paramter:Int
Field lpRect:RECT
End Type

Type RECT
...
End Type


Kann mir jemand dieses Verhalten bestätigen?
Kann ich es jetzt auch irgendwie anrichten, dass die Types tatsächlich mit Pointer referenziert werden, also nicht Inline dargestellt werden, so dass T1 wirklich nur 8 Byte lang ist?

MfG
Der Eisvogel
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

maximilian

BeitragSa, Jun 25, 2011 15:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie hast du denn die Größe gemessen? Eigentlich werden nur die Referenzen gespeichert...
Variety is the spice of life. One day ignore people, next day annoy them.

Der Eisvogel

BeitragSa, Jun 25, 2011 15:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja ganz einfach. Ich habe eine API Funktion die mir eine Stuktur zurück gibt, die genau 8 Byte lang ist. Je 4 Bytes enthielten einen Pointer zu einer anderen Stuktur. Also das Verhalten was ich von BlitzMax erwartet hatte. Bei dem Versuch mittels BlitzMax Type auf die Stuktur zuzugreifen kamen völlig absurde Ergebnisse zustande. Somit weiß ich BlitzMax hat die Element inline abgefragt und nicht weiter referenziert. Wenn ich die Felder von T1 als Byte Ptr deklaiere und mit entsprechen Offsets darauf zugreife bekomme ich genau was ich will.
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

mpmxyz

BeitragSa, Jun 25, 2011 16:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Bist du bei Extern-Types?
Deren Inhalt wird nämlich meines Wissens nach direkt in der Variable gespeichert. (<-So dachte ich es zumindest. -> Edit)
Ein Beispiel:
BlitzMax: [AUSKLAPPEN]
Extern
Type _RECT
Field _left:Int
Field _top:Int
Field _right:Int
Field _bottom:Int
EndType
EndExtern

-> Jede _RECT-Variable ist 16 Bytes groß. (Der Pointer zu diesem Speicherbereich wird über Varptr bestimmt.)
Dadurch wird aus einer Kombination von mehreren dieser Types ein großer Speicherbereich.
Als Lösung würde ich entsprechende Pointer nutzen.
EDIT:
Inzwischen bin ich schlauer:
In C sind diese Types z.B. structs und dem entsprechend bilden sie dort den Speicherbereich einer Variable.
BlitzMax bildet immer Referenzen, egal ob man diese im nicht-Extern-Teil oder im Extern-Teil nutzt.
EDIT2:
Diese structs sind eher C++-Structs/Klassen mit einem virtual-Destruktor.
mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer
  • Zuletzt bearbeitet von mpmxyz am Sa, Jun 25, 2011 17:35, insgesamt 4-mal bearbeitet

Der Eisvogel

BeitragSa, Jun 25, 2011 16:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Nein, ich befinde mich nicht in Extern Types. Ich dachte jedoch, dass BlitzMax die automatisch mit Pointer referenziert und nicht direkt in den Type selbst einbettet. Ich wollte das nur bestätigt haben, da es mich gewundert hatte.

Ich habe das ganze im Moment über Wrapper Funktionen gelöst, aber irgendwas will immernoch nicht.
Also derzeit arbeite ich mit einem UnhandledExceptionFilter. Dazu habe ich mir die nötigen Strukturen gewrapped u.a. diese mega CONTEXT-Struktur.
Ich möchte mit dem Handler einen Hardware-Breakpoint abfangen. Das Setzen des Breakpoint klappt prima. Ohne meinen Handler, bekommt ihn BlitzMax selbst ab und bricht mit einer Fehlermeldung "EXCEPTION_SINGLE_STEP". Jetzt kommt mein Handler ins Spiel. Alles klappt prima beim Setzen. Auch die Abfrage der SINGLE_STEP-Exception funktioniert. Jetzt das Problem, der Code nach dem Breakpoint wird nicht mehr ausgeführt, wenn der Breakpoint sitzt. Also gehe ich mal davon aus, dass irgendwas im Speichermanagement schief geht. Irgendwo bei den Types muss der Hund begraben liegen. Wenn ich die auskommentiere Zeile vor "Print ..." im Handler einfüge, welche die Veränderten Daten wieder in den Speicher schreibt, wird noch nicht mal mehr Print im Handler selbst mehr ausgeführt.

Der Code ist aufgrund der Großen Strukturen sehr lang:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Const SIZE_OF_80387_REGISTERS:Int = 80
Const EXCEPTION_MAXIMUM_PARAMETERS:Int = 15
Const MAXIMUM_SUPPORTED_EXTENSION:Int = 512



Type EXCEPTION_POINTERS
Field ExceptionRecord:EXCEPTION_RECORD
Field ContextRecord:CONTEXT


Method New()
End Method


Function FromMem:EXCEPTION_POINTERS(mem:Byte Ptr)
Local ExceptionPointers:EXCEPTION_POINTERS = New EXCEPTION_POINTERS
ExceptionPointers.Create(mem)
Return ExceptionPointers
End Function

Method Create(mem:Byte Ptr)
ExceptionRecord = EXCEPTION_RECORD.FromMem(Byte Ptr(Int Ptr(mem)[0]))
ContextRecord = CONTEXT.FromMem(Byte Ptr(Int Ptr(mem)[1]))
End Method


Method ToMem(mem:Byte Ptr)
ContextRecord.ToMem(Byte Ptr(Int Ptr(mem)[1]))
End Method
End Type


Type EXCEPTION_RECORD
Field ExceptionCode:Int
Field ExceptionFlags:Int
Field ExceptionRecord:EXCEPTION_RECORD
Field ExceptionAddress:Int
Field NumberParameters:Int
Field ExceptionInformation:Byte[EXCEPTION_MAXIMUM_PARAMETERS]


Method New()
End Method


Function FromMem:EXCEPTION_RECORD(mem:Byte Ptr)
Local ExceptionRecord:EXCEPTION_RECORD = New EXCEPTION_RECORD
ExceptionRecord.Create(mem)
Return ExceptionRecord
End Function


Method Create(mem:Byte Ptr)
Local intMem:Int Ptr = Int Ptr(mem)

ExceptionCode = intMem[0]
ExceptionFlags = intMem[1]
If intMem[2] Then ExceptionRecord = FromMem(Byte Ptr(intMem[2]))
ExceptionAddress = intMem[3]
NumberParameters = intMem[4]
MemCopy(ExceptionInformation, mem + $14, EXCEPTION_MAXIMUM_PARAMETERS)
End Method
End Type


Type CONTEXT
Global SIZE:Int = $02CC

Field ContextFlags:Int

Field Dr0:Int
Field Dr1:Int
Field Dr2:Int
Field Dr3:Int
Field Dr6:Int
Field Dr7:Int

Field FloatSave:FLOATING_SAVE_AREA

Field SegGs:Int
Field SegFs:Int
Field SegEs:Int
Field SegDs:Int

Field Edi:Int
Field Esi:Int
Field Ebx:Int
Field Edx:Int
Field Ecx:Int
Field Eax:Int

Field Ebp:Int
Field Eip:Int
Field SegCs:Int
Field EFlags:Int
Field Esp:Int
Field SegSs:Int

Field ExtendedRegisters:Byte[MAXIMUM_SUPPORTED_EXTENSION]


Method New()
FloatSave = New FLOATING_SAVE_AREA
End Method

Function FromMem:CONTEXT(mem:Byte Ptr)
Local ctx:CONTEXT = New CONTEXT
ctx.Create(mem)
Return ctx
End Function

Method Create(mem:Byte Ptr)
Local intMem:Int Ptr = Int Ptr(mem)

ContextFlags = intMem[0]

Dr0 = intMem[1]
Dr1 = intMem[2]
Dr2 = intMem[3]
Dr3 = intMem[4]
Dr6 = intMem[5]
Dr7 = intMem[6]

FloatSave.ControlWord = intMem[7]
FloatSave.StatusWord = intMem[8]
FloatSave.TagWord = intMem[9]
FloatSave.ErrorOffset = intMem[10]
FloatSave.ErrorSelector = intMem[11]
FloatSave.DataOffset = intMem[12]
FloatSave.DataSelector = intMem[13]
MemCopy(FloatSave.RegisterArea, mem + $34, SIZE_OF_80387_REGISTERS)
FloatSave.Cr0NpxState = intMem[34]

SegGs = intMem[35]
SegFs = intMem[36]
SegEs = intMem[37]
SegDs = intMem[38]

Edi = intMem[39]
Esi = intMem[40]
Ebx = intMem[41]
Edx = intMem[42]
Ecx = intMem[43]
Eax = intMem[44]

Ebp = intMem[45]
Eip = intMem[46]
SegCs = intMem[47]
EFlags = intMem[48]
Esp = intMem[49]
SegSs = intMem[50]

MemCopy(ExtendedRegisters, mem + $CC, MAXIMUM_SUPPORTED_EXTENSION)
End Method


Method ToMem:Byte Ptr(mem:Byte Ptr = Null)
If Not mem Then mem = MemAlloc(SIZE)

Local intMem:Int Ptr = Int Ptr(mem)

intMem[0] = ContextFlags

intMem[1] = Dr0
intMem[2] = Dr1
intMem[3] = Dr2
intMem[4] = Dr3
intMem[5] = Dr6
intMem[6] = Dr7

intMem[7] = FloatSave.ControlWord
intMem[8] = FloatSave.StatusWord
intMem[9] = FloatSave.TagWord
intMem[10] = FloatSave.ErrorOffset
intMem[11] = FloatSave.ErrorSelector
intMem[12] = FloatSave.DataOffset
intMem[13] = FloatSave.DataSelector
MemCopy(mem + $34, FloatSave.RegisterArea, SIZE_OF_80387_REGISTERS)
intMem[34] = FloatSave.Cr0NpxState

intMem[35] = SegGs
intMem[36] = SegFs
intMem[37] = SegEs
intMem[38] = SegDs

intMem[39] = Edi
intMem[40] = Esi
intMem[41] = Ebx
intMem[42] = Edx
intMem[43] = Ecx
intMem[44] = Eax

intMem[45] = Ebp
intMem[46] = Eip
intMem[47] = SegCs
intMem[48] = EFlags
intMem[49] = Esp
intMem[50] = SegSs

MemCopy(mem + $CC, ExtendedRegisters, MAXIMUM_SUPPORTED_EXTENSION)

Return mem
End Method
End Type


Type FLOATING_SAVE_AREA
Field ControlWord:Int
Field StatusWord:Int
Field TagWord:Int
Field ErrorOffset:Int
Field ErrorSelector:Int
Field DataOffset:Int
Field DataSelector:Int
Field RegisterArea:Int[SIZE_OF_80387_REGISTERS]
Field Cr0NpxState:Int
End Type



Extern "Win32"
Function GetCurrentThread:Int()

Function SetThreadContext(hThread:Int, lpContext:Byte Ptr)
Function GetThreadContext(hThread:Int, lpContext:Byte Ptr)
Function SetUnhandledExceptionFilter:Byte Ptr(lpTopLevelExceptionFilter:Byte Ptr)

Function GetLastError:Int()
End Extern


Const STATUS_SINGLE_STEP:Int = $80000004
Const EXCEPTION_SINGLE_STEP:Int = STATUS_SINGLE_STEP
Const EXCEPTION_CONTINUE_SEARCH:Int = 0
Const EXCEPTION_CONTINUE_EXECUTION:Int = 1

Function UnhandledExceptionFilter:Int(ExceptionInfoPtr:Byte Ptr)
Local ExceptionInfo:EXCEPTION_POINTERS = EXCEPTION_POINTERS.FromMem(ExceptionInfoPtr)

If ExceptionInfo.ExceptionRecord.ExceptionCode = EXCEPTION_SINGLE_STEP Then
If ExceptionInfo.ExceptionRecord.ExceptionAddress = dwBreakPoint Then
ExceptionInfo.ContextRecord.Eip:+nBreakPointJump
'ExceptionInfo.ToMem(mem)
Print "Exception Handler"
Return EXCEPTION_CONTINUE_EXECUTION
EndIf
EndIf

MemFree(ExceptionInfo)

Return OldUnhandledExceptionFilter(ExceptionInfoPtr)
End Function


Const CONTEXT_i386:Int = $10000
Const CONTEXT_CONTROL:Int = CONTEXT_i386 | $1
Const CONTEXT_INTEGER:Int = CONTEXT_i386 | $2
Const CONTEXT_SEGMENTS:Int = CONTEXT_i386 | $4
Const CONTEXT_FLOATING_POINT:Int = CONTEXT_i386 | $8
Const CONTEXT_DEBUG_REGISTERS:Int = CONTEXT_i386 | $10
Const CONTEXT_EXTENDED_REGSITERS:Int = CONTEXT_i386 | $20
Const CONTEXT_FULL:Int = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS


Global dwBreakPoint:Int = Int(Byte Ptr(BreakPoint))
Global nBreakPointJump:Int = 0


Global oldHandler:Byte Ptr = SetUnhandledExceptionFilter(UnhandledExceptionFilter)
If oldHandler Then Notify("Exception Handler set!")
Global OldUnhandledExceptionFilter:Int(ExceptionInfo:Byte Ptr) = oldHandler

Global ctx:CONTEXT = New CONTEXT
Global mem:Byte Ptr = MemAlloc($2CC)

ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS
ctx.Dr6 = 0
ctx.Dr0 = dwBreakPoint
ctx.Dr7 = 1
ctx.ToMem(mem)

If SetThreadContext(GetCurrentThread(), mem) Then Notify("Hardware-Breakpoint set!")


BreakPoint()


Function BreakPoint()
Print "Function called."
End Function
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

maximilian

BeitragSa, Jun 25, 2011 17:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Eisvogel hat Folgendes geschrieben:
Naja ganz einfach. Ich habe eine API Funktion die mir eine Stuktur zurück gibt, die genau 8 Byte lang ist. Je 4 Bytes enthielten einen Pointer zu einer anderen Stuktur. Also das Verhalten was ich von BlitzMax erwartet hatte. Bei dem Versuch mittels BlitzMax Type auf die Stuktur zuzugreifen kamen völlig absurde Ergebnisse zustande. Somit weiß ich BlitzMax hat die Element inline abgefragt und nicht weiter referenziert. Wenn ich die Felder von T1 als Byte Ptr deklaiere und mit entsprechen Offsets darauf zugreife bekomme ich genau was ich will.


Kannst du mir mal bitte erklären wie du überhaupt das BMax-Objekt erhalten hast? Denn die API-Funktion kann die ja gar nicht zurückgegeben haben, sondern lediglich Byte Ptrs. Und die kann man nicht zu BMax-Objekten casten.

Sorry für die kurzen Posts, aber ich glaube du beschuldigst hier BMax eines Verhaltens, dass allein auf dich zurückzuführen ist.
Variety is the spice of life. One day ignore people, next day annoy them.

Der Eisvogel

BeitragSa, Jun 25, 2011 18:07
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzMax Types sind nichts anderes als Pointer auf einen Speicherbereich. So wie jede andere Sturktur auch. Schreib einfach als Rückgabewert der API Funktion den Namen deines Types und fertig. Bestes Beispiel wieder die RECT Struktur. Ein Pointer auf einen 16 Byte langen Speicherbereich. Genau diesen Speicherbereich kannst du auch als Type nachbauen.
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Holzchopf

Meisterpacker

BeitragSa, Jun 25, 2011 19:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich könnte schwören, dass BMax Unter-Types nicht einbettet, sondern tatsächlich nur referenziert. Sonst ginge das hier schon mal nicht:
BlitzMax: [AUSKLAPPEN]
Type TTest
Field a:TTest
End Type


Und, ob BMax-Types wirklich Nichts anderes sind als Byte Ptr würde ich so auch nicht unterschreiben. Zwar zeigt Varptr eines Types auf das erste Feld im Type, aber ich glaube, da versteckt sich noch ein Header davor. Wie machst du denn aus dem Byte Ptr von der API einen BMax-Type?

BlitzMax: [AUSKLAPPEN]
Type T1
Field a:T2
Field b:T2
End Type

Type T2
Field c:Int
Field d:Int
End Type

Print SizeOf(T1)

-> 8 Byte (aber eben, BMax wird wahrscheinlich noch zusätzliche Bytes für Headerdaten reservieren).

mfG
Holzchopf
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Der Eisvogel

BeitragSa, Jun 25, 2011 19:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Es kann durchaus sein, das BM da noch andere Daten hat, aber der eigentlich Zeiger der sich in jeder Variable verbirgt zeigt immer auf das erste Feld.

Zu deinem ersten Code stimme ich dir zu, aber da könnte es ja irgendwie ne andere Handhabung geben, oder so.

Wenn man eine API Funktion einbindet, die zB eine RECT Struktur zurückgibt machst du das so:
BlitzMax: [AUSKLAPPEN]
Extern "Win32"
Function TolleAPIFunktion:RECT(und:Int, noch:Byte, ein:Short, paar:Byte Ptr, parameter:RECT)
End Extern

Type RECT
Field Left:Int
Field top:Int
Field Right:Int
Field bottom:Int
End Type


Das funktioniert prima.
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Noobody

BeitragSa, Jun 25, 2011 22:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Eisvogel hat Folgendes geschrieben:
BlitzMax Types sind nichts anderes als Pointer auf einen Speicherbereich. So wie jede andere Sturktur auch. Schreib einfach als Rückgabewert der API Funktion den Namen deines Types und fertig.

Das geht so nicht. BMax-Types sind nicht einfach nur Speicherbereiche, die man beliebig herumcasten kann, sondern Objekte mit Metadaten (um Polymorphie und Reflection zu erlauben), die zudem noch vom GC verwaltet werden. Du kannst also nicht einfach einen Rückgabewert der WinAPI in einen Type casten und C-ähnliches Verhalten erwarten.

In deinem Fall musst du also den Rückgabewert der API-Funktion wie einen gewöhnlichen Speicherbereich mit Zeigern verwalten. Wenn das Struct keine Pointer enthält, könntest du alternativ dessen Inhalt mit MemCopy in einen Type kopieren, aber das ist auch eine eher gefährliche Lösung (man hat ja keine Garantie, in welcher Reihenfolge Typefelder im Speicher liegen).
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Holzchopf

Meisterpacker

BeitragSa, Jun 25, 2011 23:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Noobody hat Folgendes geschrieben:
alternativ dessen Inhalt mit MemCopy in einen Type kopieren
Sowas habe ich auch schon versucht. Aber immer, wenn ich den Pointer zu 'nem Type als Schreib-Adresse missbrauche, jagt's mir BMax um die Ohren. Auslesen geht Problemlos. Aber schreiben - keine Chance.
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Noobody

BeitragSa, Jun 25, 2011 23:09
Antworten mit Zitat
Benutzer-Profile anzeigen
@Holzchopf: Die Speicheradresse des Types sollte man nicht nehmen, da man sonst oben erwähnte Header überschreibt. Stattdessen einfach den Zeiger auf das erste Feld nehmen: BlitzMax: [AUSKLAPPEN]
Local Rect:TRect = New TRect
Local RectArray:Int[] = [3, 46, 123, 1337]

MemCopy Varptr Rect.X, Varptr RectArray[0], 4*4

Print Rect.X + " " + Rect.Y + " " + Rect.W + " " + Rect.H

Type TRect
Field X:Int, Y:Int, W:Int, H:Int
End Type
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Holzchopf

Meisterpacker

BeitragSa, Jun 25, 2011 23:25
Antworten mit Zitat
Benutzer-Profile anzeigen
:O Achso - und ich Referenzierte immer auf die Type-Instanz...

Na, dann ist ja Types kopieren doch auch möglich BlitzMax: [AUSKLAPPEN]
Local Rect:TRect = New TRect
Local Rect2:TRect = New TRect
Local RectArray:Int[] = [3, 46, 123, 1337]

Rect.name = "Spartaaaaaaaaaa!"
' Vom Array zum Type
MemCopy Varptr Rect.X, Varptr RectArray[0], 4*4
' und den Type Kopieren
MemCopy Varptr Rect2.X, Varptr Rect.X, SizeOf(TRect)

Print Rect.name +": " +Rect.X + " " + Rect.Y + " " + Rect.W + " " + Rect.H
Print Rect2.name +": " +Rect2.X + " " + Rect2.Y + " " + Rect2.W + " " + Rect2.H

Type TRect
Field X:Int, Y:Int, W:Int, H:Int
Field name:String
End Type


Aber das wurde glaube ich nicht in diesem Thread gefragt... *mir müde die Augen reib*
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Der Eisvogel

BeitragSa, Jun 25, 2011 23:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, bisher ist nie was schief gegangen. Der Zeiger des Types lag immer auf dem ersten Feld und die Felder waren immer perfekt angeordnet. Aber ich hab es jetzt doch über Wrapper gelöst.
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group