Problem mit Pixmap
Übersicht

![]() |
PebenderBetreff: Problem mit Pixmap |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo,
mir ist schon öfters ein Problem mit Pixmap aufgefallen, hat bei mir noch nie funktioniert, warum, deswegen frage ich jetzt hier: Hier ein Beispiel von 2dgamecreaters : Code: [AUSKLAPPEN] SuperStrict
Import MaxGUI.drivers Local MyWindow:TGadget=CreateWindow("Panel Example", 200,200,320,240) Local MyPanel:TGadget=CreatePanel(110,30,80,80, MyWindow) Local image:TPixmap=LoadPixmap AppDir$+("/image/delete.png") Repeat WaitEvent() Select EventID() Case EVENT_WINDOWCLOSE End End Select SetPanelPixmap MyPanel, image, PANELPIXMAP_CENTER Forever kommt eine fehlermeldung: Compile Error: Unable to convert from 'TPixmap(object) to 'brl.pixmap.TPixmap' Die Frage die sich mir stellt ist einfach, ich habe schon mehrere Beispiele mit TPixmap probiert, keines funktioniert. Muß ich noch etwas anderes auser die MaxGui importieren ??? mfg Peter |
||
BMax & MaxGUI |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bei deinem gezeigten Code kommt der Fehler auch.
Das Problem liegt nicht in den verwendeten Types sondern darin, dass Funktionsaufrufe ohne den Klammern in Blitz zwar zulässig sind, aber nur, wenn der Rückgabewert nicht verwendet wird. Die Zeile BlitzMax: [AUSKLAPPEN] Local image:TPixmap=LoadPixmap AppDir$+("/image/delete.png") kann also nicht funktionieren, da hier der Rückgabewert der Funktion LoadPixmap() abgefragt wird, was nicht geht (wäre das zulässig könnte es Mehrdeutigkeiten verursachen). Die Zeile BlitzMax: [AUSKLAPPEN] LoadPixmap AppDir$+("/image/delete.png") (also ohne der Zuweisung) lässt er durchgehen, ist aber sinnlos, da diese Funktion ohne Rückgabewert sinnlos ist. Was also getan werden muss ist Folgendes: BlitzMax: [AUSKLAPPEN] Local image:TPixmap=LoadPixmap(AppDir$+("/image/delete.png")) Der Aufruf mit den hinzugefügten Klammern funktioniert jetzt ohne Probleme, da mit den Klammern der Rückgabewert abgerufen werden kann. Generell empfiehlt sich Funktionsaufrufe immer mit den Klammern zu machen, auch wenn es keine Parameter gibt (z.B. foo() ), da es dann solche Probleme nicht gibt und es die Lesbarkeit vereinfacht. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Als Ergänzung, wieso das so ist: Klingt im ersten Moment vielleicht unlogisch, aber das ganze hat seinen Grund. Kann jetzt nicht garantieren, dass es bei Blitzmax genauso ist, aber ungefähr in der Art. Bei der Zeile:
BlitzMax: [AUSKLAPPEN] Local image:TPixmap=LoadPixmap AppDir$+("/image/delete.png") liest der Compiler bis LoadPixmap und dann kommt keine Klammer, ergo willst du nicht den Rückgabewert der Funktion zurückgeben, "denkt" sich der Compiler zumindest. Also versucht er zuerst Mal die Funktion LoadPixmap, die den Typ TPixmap(Object) hat, nach TPixmap zu casten. Kann nicht funktionieren. Was DAK geschrieben hat, ist natürlich komplett richtig und eigentlich auch genug. Nur falls es dich interessiert, wie das zustande kommt. |
||
![]() |
Pebender |
![]() Antworten mit Zitat ![]() |
---|---|---|
vielen Dank ihr beiden, klingt einleuchtend.
Mich wundert nur, das die ganze Beispiele die ich getestet habe nicht funktioiert haben. Naja, jetzt weiß ich zumindest wie das geht. mfg |
||
BMax & MaxGUI |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Thunder: Dabei bin ich gerade auf was wirklich Lustiges gekommen, was ich so vorher noch nicht gekannt habe (nehme an, du aber wohl schon): Man kann in BM Funktionen in Variablen speichern und von dort aufrufen, ganz ohne irgendwelche Pointer oder so.
BlitzMax: [AUSKLAPPEN] Local f:TPixmap(x:Object)=LoadPixmap |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Jup, habe diese Schreibweise schon Mal gesehen (kann gerade aber nicht sagen wo).
BlitzMax: [AUSKLAPPEN] Local f:TPixmap(x:Object) entspricht in BlitzMax der Deklaration eines Funktionspointers. Weil Klammern aufscheinen und Local/Global/Field nicht dazu bestimmt sind, Funktionen zu definieren, wird da automatisch ein Funktionspointer draus. Daher nimmt dir BlitzMax die Dereferenzierung auch ab. Wäre f ein primitiver Pointer bräuchtest du ja eckige klammern. BlitzMax: [AUSKLAPPEN] f = LoadPixmap ' weise dem Zeiger eine Adresse einer Funktion zu Sowas ist voll nützlich wenn man am Anfang von einem Programm Einstellungen vornimmt und für eine bestimmte Aufgaben zwei Funktionen schreibt. Die eine, die möglichst mit allen Geräten kompatibel ist, und eine andere, die zwar höhere Performance erzielt, aber nur unter gewissen Umständen gebraucht werden kann. Zum Beispiel wenn man sich Prozessorerweiterungen (MMX, SSE) zu Nutze machen will. Dann verwendet man einen Pointer und setzt am Anfang des Programms diesen auf eine der beiden Funktionen. Eben auf die, die besser funktioniert. |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich hab gedacht, dass es in BlitzMax nur Funktionspointer (per byte ptr so wie du gemeint hast) gibt. Die Funktionsreferenzen wie sie hier gezeigt sind, habe ich in BlitzMax nicht gekannt.
Sind ja eigentlich Referenzen, keine Pointer. Der Unterschied ist, dass Pointer verrechenbar sind, also dass man z.B. die Adresse des Pointers +1 rechnen kann. Referenzen können nur auf Objekte oder Funktionen gesetzt werden. BlitzMax: [AUSKLAPPEN] Local f:Int() = MilliSecs 'geht bei Pointern und Referenzen Pointer sind mächtiger (man kann dann z.B. so durch ein Array aus Funktionspointern durchiterieren, indem man den Funktionspointer jedes Mal um 1 erhöht), dafür sind Referenzen sicherer weil sie zeigen immer nur auf gültige Funktionen oder Null. Ein Funktionspointer kann auf jeden Teil des Speichers zeigen, auch auf Teile, die keine Funktionen sind, was zu echten Problemen führen kann. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Jaaa.. es stimmt schon, dass es nicht wirklich Zeiger sind, aber es sind auch nicht wirklich Referenzen. Denn sonst könnte ich nicht einfach einen Byte Ptr zuweisen oder?
BlitzMax: [AUSKLAPPEN] SuperStrict Es ist am ehesten ein Funktionszeiger mit Parameterprüfung. Ich kann f nämlich nur so aufrufen, wie ich es deklariert habe, aber f muss nicht zwingend auf eine Funktion zeigen. |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Oder eine Referenz mit sehr schlechter Parameterprüfung ^^
Ja, du hast recht, es ist ein Zwischending. Nimm mir es nicht böse, aber dein Code schaut irgendwie so falsch aus, wie etwas, das gar nicht sein sollte^^ Vielleicht programmier ich auch schon zu lange in Java^^ |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Tu ich nicht ![]() Die starke Typisierung von Java macht es irgendwie idiotensicher, denn man wird vor jedem Cast gewarnt und kann sich dann fragen, ob man es wirklich will. Für mich ist das vergleichbar mit der UAC von Windows, die immer fragt, ob ich dies oder jenes wirklich will, und ich bin ja eher bei C und Assembler zuhause, die voraussetzen, dass man weiß, was man tut^^ (nimm mir das nicht böse ![]() Daher finde ich auch toll, dass BlitzMax so viel mit sich machen lässt und so viel implizit castet. Was es wahrscheinlich etwas schwieriger macht, für eine BlitzMax-ähnliche Sprache einen Compiler zu schreiben... :/ Habs jedenfalls noch nicht hingekriegt. |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem ist beim impliziten Casten imho nicht wenn es funktioniert, sondern wenn die Regeln, nach denen gecastet wird, nicht offensichtlich oder mehrdeutig sind. Ein paar Beispiele dazu:
BlitzBasic: [AUSKLAPPEN]
Überhaupt sind verlustbehaftete Casts problematisch, da man da nie weis, wie sie sich verhalten. Dafür ist das letzte Beispiel ganz gut. Ein cast von einem Float in einem String ("1.6") wird, beim Casten nach Int, mit einem Truncate abgerundet (egal was die Nachkommawerte sind, es wird abgerundet). Ein cast von Float nach Int wird hingegen gerundet, also >=1.5 wird aufgerundet, ansonsten abgerundet. Außerdem ignoriert er einfach alle Nicht-Zahlenwerte und gibt keine Fehlermeldung aus. Gerade das Beispiel mit dem Komma könnte für größere Probleme sorgen, wenn jemand Werte mit einem Komma statt einem Punkt eingibt (in Mitteleuropa bevorzugt man ja das Komma dem Punkt). Ein anderes Beispiel dafür wäre folgendes: "Gib den Verkaufspreis für deine Aktien ein". Der User tippt schnell und ohne zu schauen, erwischt dabei folgende Tasten: "1u2" statt "172" und bestätigt. BB würde den Input als 1 interpretieren, statt einen Fehler zu werfen, auf den hin man dem User z.B. ein Popup mit "Bitte nur Zahlen eingeben" zeigen könnte. Die Sache mit dem "voraussetzen, dass man weiß was man tut" ist so eine Sache. Du kennst doch sicher den Spruch von wegen "Ein Programm ist entweder extrem kurz oder beinhaltet Fehler". So richtig immer ganz sicher aufpassen, dass alles richtig geht, kann man gar nicht. Das ist auch der Grund, warum auch immer noch bis jetzt Hacker Buffer Overflows verwenden können, um ihren Zielprogrammen Schadcode einzuschleusen. In Sprachen wie Java gibt es Buffer Overflows gar nicht. Die starke Typisierung in Java macht auch die Fehlersuche viel einfacher. Damit finde ich die meisten Bugs schon bevor ich den Compiler überhaupt anschmeiße, da schon in der IDE die ganzen Fehler angezeigt werden (ok, das rennt über den Compiler aber trotzdem). In C, wenn man da irgendwo im Programm einen Fehler hat, der durch implizites Casten unterschlagen wird, dann taucht der im besten Fall beim Testen auf, indem das Programm abschmiert oder einen Laufzeitfehler wirft. Wenn man Pech hat, dann taucht der da gar nicht auf, sondern propagiert sich und verursacht dann ganz wo anders im Programm kräftigere Fehler (z.B. kaputte Speicherstände). Ich hab letztens meinem Schwager C-Nachhilfe geben müssen (für einen Einführungskurs an der FH). Was da an komischen Fehlern gekommen ist war einfach nur grausam. Oder eher, was nicht für Fehler gekommen sind. Falscher Datentyp bei der Textausgabe, hat aber nicht die Ausgabe des Textes an der Stelle beeinflusst, sondern einfach nur dafür gesorgt, dass nach zwei (!) weiteren Ausgaben die Ausgabe abgestürzt ist. Da haben wir gut eine Viertelstunde nach dem Fehler gesucht (obwohl das Programm echt trivial war). In Java hätte uns das die IDE während dem Tippen angezeigt, das wir da Mist machen (inklusive was man ändern sollte), und kompilieren hätte es uns auf keinen Fall lassen. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Gut, das stimmt. Und implizite Casts von Strings aus BB ins Spiel zu bringen ist wirklich gemein ![]() Implizite Casts von Strings würde ich auch nicht wollen (ist auch aus lowlevel-Sicht völlig unsinnig). Gehen auch in C und asm nicht, bzw. kriegt man einfach die Adresse des Strings in die Int-Variable. In Java gibt es andere Sicherheitslücken, und die sind nicht viel weniger heftig (z.B. die zwei großen, die Oracle letztes Jahr zu beheben hatte). Java (bzw. die Entwickler von Java-VMs) hat/haben auch irgendwie eine Art Verpflichtung, keine Sicherheitslücken zu haben, weil die Java-Entwickler darauf vertrauen. Ein C-Programmierer muss sich im klaren sein, dass er allein für Fehler verantwortlich ist und muss dementsprechend verantwortungsbewusst programmieren. Zusätzlich hat er die Möglichkeit sein Programm so zu tunen, dass es möglichst effizient ist. Ja, C ist auch ziemlich minimalistisch. Bei der Ausgabe ist die Anzeige von Fehlern nicht möglich, weil printf einfach eine Funktion ist, der man so viele Parameter geben kann, wie man will (mindestens einen), und dass im Format-String definiert sein muss, wieviele Parameter noch kommen. Da muss man einfach aufpassen, was man tut ![]() Das Problem hierbei ist, dass der C-Standard schon sehr alt ist und nicht unbedingt aus einer Zeit, wo man sich über Sicherheit so viele Gedanken gemacht hat (es gab auch wenig Grund dazu). |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Joa, es hat alles seine Anwendungsgebiete. Einen Grafiktreiber in Java schreiben könnte etwas fehl am Platz sein und auch einen Mikrocontroller würde ich nicht mit Java überladen.
Aber gleichzeitig würde ich keine halbwegs sicherheitskritischen Sachen oder größere Projekte in C machen (bzw. C dann nur für die Teile davon verwenden, wo es notwendig wäre). Meiner Meinung nach ist Java C zu Ende gedacht. Oder zumindest weiter gedacht. Dass es in den letzten 30 Jahren seit C als Standard festgelegt wurde, es noch weitere Entwicklungen gab, was Programmiersprachen angeht, ist vollkommen klar. Genauso wie z.B. es kaum noch einen Grund gibt, warum man einen Single-Pass-Compiler braucht (Stichwort Funktionsprototypen/Vorwärtsreferenzen). Die Java-Sicherheitslücken waren kein Problem der Entwickler, sondern der VM, durch die z.B. bösartige Applets aus der Sandbox ausbrechen haben können, und somit Veränderungesän am Betriebssystem vornehmen haben können. In C gibt es solche Sicherheitslücken nicht, da in C geschriebene Programme von Haus aus vollen Zugriff auf alles haben, was das Betriebssystem sie lässt. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Große Projekte in C fordern halt mehr Konzentration und Verantwortungsbewusstsein vom Programmierer, aber man hat auch Wege gefunden, in C sicher zu programmieren. Egal, was du sagst stimmt, es ist etwas veraltet und eher nur von Teile von Software noch zu gebrauchen.
Aber Java und C haben nichts als die Basis-Syntax gemeinsam. Java ist nicht C zu Ende gedacht, sondern man hat Java diese Syntax gegeben, weil viele Programmierer sie schon kannten und dann eine neue objektorientierte Sprache auf dieser Syntax aufgebaut. Man bedenke z.B., dass ein long in C nicht dasselbe ist wie in Java und es nur seehr wenige keywords in C gibt, also auch sehr wenig Übereinstimmung mit Java. D ist C zu Ende gedacht ![]() Wir sollten dann übrigens Mal aufhören, gell? Bevor das hier ein Flamewar wird oder so ^^ |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group