Methode zu Object

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

sinjin

Betreff: Methode zu Object

BeitragDi, Okt 07, 2014 5:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie bekomme ich die Physikalische Addresse eine Methode heraus.
Bei einer Funktion geht ja folgendes:

Code: [AUSKLAPPEN]

function test:object()
  print "test"
endfunction
local run:object()=test
run


Eine Methode ist ja nichts anderes als eine Funktion mit Übergabewert (self).
Wie geht es nun mit Methoden? Bei Folgendem Code bekomme ich folgenden fehler: Unable to convert from 'Object()' to 'Object()'

Code: [AUSKLAPPEN]

type test1
  method draw:object()
    print "test"
  endmethod
endtype

global t1:test1=new test1
global aha:object()
aha=t1.draw  'test1.draw
aha


Wenn es so nicht geht, sollte es mit Assembler gehen indem man es ungefähr so macht:

Code: [AUSKLAPPEN]

function callmethod(caller:object(),instance:object)
  _callmethod caller,instance
endfunction

type test1
  method draw:object()
    print "test"
  endmethod
endtype

global t1:test1=new test1
global aha:object()
callmethod t1.draw,t1


Und der Assemblercode dazu müsste ungefähr so aussehen, leider kennt er dword ptr nicht...

Code: [AUSKLAPPEN]

format MS COFF
public __callmethod
__callmethod:
  push ebp
  sub esp,8
  call [dword ptr ss:esp]
  pop ebp
ret

BladeRunner

Moderator

BeitragDi, Okt 07, 2014 8:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
Import BRL.Reflection

Type MyType
   Global C:Int = 7
   
   Method AMethod:Int(B:Int)
      Return B+C
   EndMethod
End Type

Local AType:MyType = New MyType

Local AMethod:Int( this:MyType, B:Int) = GetMethodPointer( AType, "AMethod")

Print AMethod( AType, 6)


Function GetMethodPointer:Byte Ptr( obj:Object, name:String)
   Extern "C"
      Function bbRefMethodPtr:Byte Ptr( obj:Object, index:Int )
   EndExtern
   
   Local t:TTypeId = TTypeId.ForObject(obj)
   If Not t Then Return Null
   
   Local m:TMethod = t.FindMethod(name)
   If Not m Then Return Null
   
   Return bbRefMethodPtr( obj, m._index)
EndFunction


Allerdings stellt sich mir die Frage nach dem Sinn eines Methodpointers schon ein wenig.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

sinjin

BeitragDi, Okt 07, 2014 17:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke, ich finde es wesentlich flexibler, da so mehr oder weniger die Methoden-Namen wegfallen anstatt es so zu machen:

Code: [AUSKLAPPEN]

type tsupertype
  method draw() endmethod
endtype

type tt1 extends tsupertype
  field aa%=5
  method draw()
    print "tt1 "+aa
  endmethod
endtype
type tt2 extends tsupertype
  field aa$="aha"
  method draw()
    print "tt2 "+aa
  endmethod
endtype

global supertype:tsupertype[2]
supertype[0]=new tt1
supertype[1]=new tt2
supertype[0].draw
supertype[1].draw


Ausserdem hat es den Vorteil, das man zb Raumschiffen statt Geschwindigkeit, Feuerkraft etc auch noch BELIEBIGEN Code mitgeben kann.
Und man kann sich einige IF's sparen. Normal läuft es ja so ab (Pseudocode):

repeat
if button.pressed then xor button.on,1
if button.on then do something
forever

Wenn man nun ein Array mit Methoden/Funktionen hat, fällt die zweite IF-Abfrage weg:
repeat
if button.pressed then add to arrayoffunctions(do something)
call arrayoffunctions
forever

Das mag im ersten Moment übertrieben sein, aber wenn man ein richtig fettes Programm hat, bringt das mit Sicherheit einiges.

BladeRunner

Moderator

BeitragDi, Okt 07, 2014 20:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Methodpointer sind allerdings deutlich weniger performant, da per Reflection aufgelöst. Da gefällt mir persönlich der ansatz mit der Überladung/ Vererbung deutlich besser.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Thunder

BeitragDi, Okt 07, 2014 21:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich kenn mich ja nicht mit Reflection aus, Leute, aber wenn du einen Pointer auf eine Methode hast, dann kann der nicht "weniger performant" sein als irgendein anderer Funktionspointer Surprised
Ich glaub mit meinem ObjectEx-Modul könnte sich die Adresse auch auslesen lassen... Mal sehen.

Silver_Knee

BeitragDi, Okt 07, 2014 21:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn du wirklich einzelnen Objekten Code mitgeben willst, kannst du das auch mit Funktionspointern machen:

BlitzMax: [AUSKLAPPEN]

Type Ship
Field doSpecialImpl:Object(s:Ship,data:Object)

Method doSpecial:Object(data:Object)
Return doSpecialImpl(Self,data)
End Method
End Type


Local s:Ship=New Ship
s.doSpecialImp=myFunc

Function myFunc:Object(s:Ship,data:Object)
Return data.ToString()+s.ToString()
End Function


Wenn du die externe Funktion so in eine Methode einbettest, kannst du in der Klasse den Rückgabewert bzw die Eingabedaten noch validieren/auswerten.
 

sinjin

BeitragDi, Okt 07, 2014 22:27
Antworten mit Zitat
Benutzer-Profile anzeigen
@Silver_Knee
Mir geht es ja eigentlich darum nicht für jede Methode noch eine Funktion anzulegen, das finde ich zu doppelt gemoppelt. Das Mulipliziert sich zu schnell, 3 Typen á 3 Methoden sind 9 extra Funktionen. Deshalb kam ich ja anfangs auch auf die Idee nur 1 Funktion zu schreiben die den Job übernimmt, und wenns BlitzBasic so nicht kann dann eben in Assembler, leider kann ich kaum C. Zu DOS-Zeiten habe ich nur Assembler programmiert, aber mit Windows habe ich es dann nach und nach aufgegeben.

@Thunder
Bin gespannt Very Happy

Aber danke an alle die sich dran probieren! Vielleicht kommt ja noch von jemanden eine recht einfache Lösung.

Jolinah

BeitragDi, Okt 07, 2014 22:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist wahrscheinlich auch nicht das was du suchst, aber das ist ein Ansatz den ich vor einer Weile für Event-Handler ähnlich wie bei .NET umgesetzt habe. Bei den Methoden funktioniert das auch via Reflection (wobei die Auflösung nur beim Hinzufügen einer Methode geschieht, beim Aufruf nicht mehr, da zwischengespeichert).

https://www.blitzforum.de/foru...hp?t=39969

Im wesentlichen kann man das dann so verwenden:
BlitzMax: [AUSKLAPPEN]
Local event:TMaxEvent = New TMaxEvent
'Methoden/Funktionen hinzufügen
event.AddHandlerMethodPtr(meinObjekt, "meineMethode")
event.AddHandlerFuncPtr(meineFunktion)
'Event auslösen (Funktionen/Methoden ausführen)
event.Raise(quellObjekt, eventArgumente)

...

Local button:TButton = New TButton
button.Click.AddHandlerMethodPtr(anderesObjekt, "andereMethode")
'Im Button-Update-Code wird bei einem Klick das Click.Raise(Self, clickArgs) aufgerufen, dadurch wird die Methode des anderen Objekts aufgerufen


Naja, dachte ich poste es einfach mal Smile

PS: Etwas speziell daran ist, dass immer eine Funktion mit der Signatur (quellObjekt:Object, eventArgs:TMaxEventArgs) erwartet wird. Das kommt daher, weil wie gesagt .NET das Vorbild war. Aber das könnte man ja schnell anpassen.

Thunder

BeitragDi, Okt 07, 2014 23:18
Antworten mit Zitat
Benutzer-Profile anzeigen
@sinjin: Frage: könntest du nochmal versuchen, zu erklären, warum es dir mit den Methoden-Pointern sinnvoll vorkommt? Ich habe im Moment das Gefühl, dass du momentan noch die high-level-Konstrukte nicht so begreifst, wie man sie verwendet - bitte nimm das nicht persönlich Wink
Ich bin mir ziemlich sicher, dass man die meisten sinnvollen Sachen in BlitzMax verwirklichen kann, ohne auf Assembler zurückzugreifen (ja, ich tu es auch gern - siehe ObjectEx oder mein Tutorial zu BlitzMax & C/asm).
BlitzMax ist auch gar nicht so ineffizient. Kannst dir ja mal in den .bmx Ordnern, die automatisch generiert werden die *.release.*.s-Dateien anschauen, das ist der Assemblercode.

Und zu deinem Assemblercode ganz am Anfang:
Das dword ptr kannst du dir sparen und ss: auch, weil das Stacksegment bei den Stackregistern sowieso verwendet wird (außerdem ist auf den meisten Betriebssystemen ds = es = ss).
In FASM sind die eckigen klammern das gleiche, wie wenn man ptr davor schreibt - also "call [edx]" = "call ptr edx"
Siehe auch http://flatassembler.net/docs.php?article=manual

DAK

BeitragMi, Okt 08, 2014 10:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Was du für das was du da machen willst eigentlich brauchst ist Überladung.

Wenn du ein Objekt haben willst, dass auf eine Funktion anders reagiert als andere Objekte dieser Art, dann mach einen Untertyp des Originaltyps, bei dem du die eine Funktion mit der neuen Funktion überlädst.
Das ist wesentlich sauberer.

Wenn man mit Assembler beginnt, dann lernt man den Code zu verunstalten um einzelne Prozessorzyklen an Performance herauszukitzeln. Das war in den Neunzigerjahren notwendig und ist es immer noch, wenn man auf einem ATMega oder ähnlichem programmiert. Auf einem modern i3/i5/i7 oder selbst noch auf einem Core2-Prozessor ist das reine Zeitverschwendung.
Dafür sorgst du so dafür, dass dein Code absolut unleserlich wird, da man zeitweise gar nicht mehr weiß, was diese Funktion jetzt tut, die einen Funktionspointer ausführt, der schon fünf mal herumgeschupft wurde.

Außerdem optimiert der Compiler viel für dich. Wenn du zu viele Mikrooptimierungen verwendest, dann kommt der Compiler oft nicht mehr mit, mit dem Chaos, dass du da tust, und kann nicht mehr optimieren. Funktionspointer lassen sich z.B. oft nicht inlinenen, da erst zur Laufzeit fest steht, auf welche Funktion sie zeigen, was bei kleinen Funktionen viel Performance bringen würde.

Versuche also besser, wenn du BlitzMax programmierst, es so zu verwenden, wie man BlitzMax verwenden soll, nicht so wie du sonst Assembler programmierst. Du machst deinen Code so nicht schneller, aber wohl unleserlicher. Mit etwas Pech wird es dadurch sogar noch langsamer.


@Reflection: Sobald du den Funktionspointer hast ist es gleich schnell wie einen Funktionspointer direkt zu verwenden. Einzig das Bekommen des Funktionspointers über Reflection ist langsam.
Gewinner der 6. und der 68. BlitzCodeCompo

Lobby

BeitragMi, Okt 08, 2014 12:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Psst, DAK, ich glaube du meinst Überschreiben.
TheoTown - Eine Stadtaufbausimulation für Android, iOS, Windows, Mac OS und Linux

DAK

BeitragMi, Okt 08, 2014 22:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Jaja, ist ja gut, ich habe überschreiben gemeint^^

Das kommt davon, wenn man hald immer nur auf Englisch programmiert (@Override ist die Annotation dazu in Java).
Gewinner der 6. und der 68. BlitzCodeCompo
 

sinjin

BeitragDo, Okt 09, 2014 16:27
Antworten mit Zitat
Benutzer-Profile anzeigen
@Thunder Ich finde das sinnvoll weil man halt durch die Typen sauberer Programmieren kann (OOP, logisch). Ich könnte schliesslich auch alle Variablen in ein riesen Array packen und alles in Funktionen aufsplitten. In Assembler fand ich es früher super, man legt ein Struct(Type) an, und war von den dazu gehörigen Funktionen total unabhängig. Damals habe ich zb. für eine Datei-Struktur ein Struct gehabt, und je nachdem ob Windows gerade läuft, die Funktionen für die langen Dateinamen ausgetauscht.
Ich weiss sehr wohl, dass man ds bzw ss nicht davor schreiben muss, ich finde es aber übersichtlicher, das Ergebnis verändert sich dadurch nicht und der Compiler kann so oder so nichts optimieren. Schlisslich kann ich in ds auch was anderes reinschrieben.
Ich habe mein Assemblerzeug mal hochgeladen. Alleine der Source für meine Units ist 500kb gross...ach, das waren Zeiten. http://www.file-upload.net/dow...s.rar.html
Das eine oder andere davon ist sich auch für euch interessant.
Gestern habe ich Freebasic entdeckt, das finde ich ja geil: Keyword ASM und los gehts Very Happy

Thunder

BeitragDo, Okt 09, 2014 17:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Funktion kannst du ja auswechseln wenn du Funktionspointer verwendest.
Wie das mit Methoden geht, hat Silver_Knee in einem Beispiel schon gezeigt.

Werde mir das mal durchsehen Very Happy bin selbst auch ein großer Assembler-Fan.

BladeRunner

Moderator

BeitragDo, Okt 09, 2014 20:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn Du aber wirklich sauberes OOP willst lässt Du die Finger möglichst von Pointern weg, die untergraben nämlich das Paradigma gewaltig.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group