C2102 und Back Buffer...
-
ach ja, ick komm halt jarnich klar...
also, ich habe das bereits im c++ forum gepostet, aber da waren die antworten nicht gerade-... befriedigend, bitte nicht persönlöich nehmen.
ALSOOO:
ich habe eine Surface klasse. in der habe ich ein Direct3DSurface8 Interface (bzw. einen pointer darauf) und eine funktuon GetSurface, die diesen Pointer zurück liefert (das ist nötig, da die Surface natürlich private isz).
in meiner grafik klasse habe ich nun ein array von instancen dieser klasse, diese stellen die backbuffer dar.
in der init methode der grafikklasse rufe ich nun GetBackBuffer wie folgt auf:if (FAILED(m_pIDirect3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_pSurface[i].GetSurface())))
{
// Fehler
}ich bekomme einen fehler... C2102, & benötigt l-value oder so. (der fehler ist in angegebener zeile zu suchen). nun habe ich die funktion anders aufgerufen, und zwar für den letzten paranmeter eingesetzt:
&(m_pSurface[0].GetSurface())
der fehler bleibt bestehen...
warum?? was kann ich tun...
ICH VERZWEIFLKE (obwohl, ich bin das ja inzwischen gewohnt... ;-))
danke schonmal
-
Tetris Fan schrieb:
&m_pSurface[i].GetSurface()
Da liegt der Fehler. Du kannst nicht die Adresse eines solchen Rückgabewertes angeben, das würde auch garnichts bringen... der wird ja nur lokal gespeichert und nach dem Methodenaufruf wieder gelöscht!
-
Fang mal an, Code zu schreiben, den du wenigstens verstehst. Das vermeidet solche Fehler.
Bye, TGGC
-
ich vertsehe meinen code, nur eben nicht dieses stück... ich vertsehe es schopn,a ber es scheint ja falsch zu sein. wie kann ich den fehler denn "umgehen"?
und warum ist der rückgabewetrt lokal???
-
Die ADRESSE des Rückgabewerts.
-
-
Tetris Fan schrieb:
ich vertsehe meinen code, nur eben nicht dieses stück... ich vertsehe es schopn,a ber es scheint ja falsch zu sein. wie kann ich den fehler denn "umgehen"?
Lösch mal eben dieses Stück und schreib es planvoll neu. Wenn du und alle die deinen Code lesen müssen irgendwann mal fit genug für solche Konstrukte sind, kannst du darüber nachdenken, sie zu benutzen.
Bye, TGGC
-
Tetris Fan schrieb:
ich vertsehe meinen code, nur eben nicht dieses stück... ich vertsehe es schopn,a ber es scheint ja falsch zu sein. wie kann ich den fehler denn "umgehen"?
und warum ist der rückgabewetrt lokal???Du bekommst eine Adresse von irgendwas zurück. Temporär ist sie weil sie in keine Variable gehalten wird und schnell die gültigkeit verliert.
int foo(); cout<<foo(); // Der Wert den foo() zurückgibt gibts nach dieser Zeile nicht mehr
Auf diesen flüchtigen Wert den Du zurückbekommst kannst Du keine Adresse binden. Um dies machen zu können musst Du die Adresse erst in eine Variable aufnehmen. Du kannst dann die Adresse von dieser Variablen verwenden. Zu beachten ist dabei aber das Du aufpassen musst wann diese Adresse verwendet wird.
int foo() { { int i; } // Hier gibt es i nicht mehr }
Legst Du die Variable von der Du Die Adresse nehmen willst lokal in der Funktion an kann es passieren das eine andere Routine auf diese Adresse zugreifen will die nicht mehr existent ist.
Einleuchtend sollte es hierdurch werden:
T * bar() { T t(12); return &t; }
(Bei der gelegenheit an alle ein Hallööööchen die meinen das es so geht nur weil es compiliert wird und die 12 lesen können).
Daher kam bei http://c-plusplus.net/forum/viewtopic.php?t=54465 der vorschlag die Variable global anzulegen.
Siehe zur Erklärung auch bitte http://c-plusplus.net/forum/viewtopic.php?t=54465 Beitrag 11.
-
also soll ich die Direct3DSurface global anlegen? aber dann bringt mir die ganze klasse doch nichts mehr (die surface klasse). außerdem weiß ich doch nicht, wieviele surfaces ich erstelle, bzw. durch GetBackBuffer, udn ähnlichen methoden ermittle.
mal so nebenbei, alles bisher genannte würde doch auf run-time errors hinauslaufen, ich bekomme jedoch einen compiler error... nur so nebenbei.
gibt es denn keine andere mthode außer das ding global anzulegen?? mit einer hilfsvariable habe ich es wie gedsagt shcon versucht, aber dann bekomme ich einen runtime error...
-
Hier bin ich etwas Überfragt da ich mich mit D3D nicht auskenne.
[stichel]
Aber TGGC scheint da sehr fitt zu sein. Vllt. kann man ihn ja zur Konstruktieven hilfe bewegen
[/stichel]
Aber ein runtime_error ist doch schon mal ein schritt weiter als der compiler error
Auch auf die Gefahr hin das ich müll schreibe (was aber sicherlich die Leute die sich mit D3D auskennen hervorlocken würde. Irgendwann kann man es doch nich mehr aushalten
Wenn ich das richtig sehe hast Du Dir eine Klasse geschrieben die einige Aufgaben für Dich übernehmen soll.
Hierbei hast Du geschrieben:
IDirect3DSurface8 * Surface::GetSurface() { return m_pIDirect3DSurface; }
Du brauchst nun aber IDirect3DSurface8 ** .
Eine weitere Möglichkeit (die hat nen fetten haken) wäre:
IDirect3DSurface8 ** Surface::GetSurface() { return &m_pIDirect3DSurface; }
Der Haken ist das man eigentlich keine Zeiger auf Interne Variablen vergibt da diese sonst Manipuliert werden können ohne das man etwas gegen machen kann. Nun lässt sich zwar mit const noch ein wenig was machen das mag dann aber die API nicht mehr so recht.
Der Vorteil wäre aber das jede Deiner Klassen so wie gedacht das "Surface" hält und Du eine passende Adresse zurückgibst.
Vllt. ist von der API auch die änderung der Daten wünschenswert weil eben dieser Wert permanent durch API und Deiner Klasse modifiziert werden muß.
Da muß ich passen, ich hab noch nie was mit GFX Programmierung gemacht.
P.s.: Das global sollte nur helfen herauszufinden ob später der Speicher verwendet wird nachdem Du es mit einer Lokalen variable versucht hast und es da krachte. Danach wurde ersichtlich das Du einen Speicherbereich brauchst der vermutlich die Lebenszeit des "Surface"'s üerlegeb muß.
-
Knuddlbaer schrieb:
Auch auf die Gefahr hin das ich müll schreibe
Selbsterkenntnis...
Das Beispiel passt hier nicht.@TetrisFan: Werd Dir mal klar, was dein Code machen soll. Dann verstehst du auch, warum hier nix compiliert.
-
auf die gefahr hin, mich noch unbeliebter zu machen, als ich schon bit:
ich BIN mir verdammt nochmal im klaren fdarüber, was mein code machen soll!
ich habe wie von Knuddlbaer schon gesagt, eine klasse geschrieben, die arbeit mit surfaces für mich übernimmt. sie lockt sie, unlockt sie, begoinnt das rendering auf sie und beendet es, sie kann einzelne pixel zurück liefern und setzen, etc.
aaußerdem enthält sie noch daten, wie eine D3DSURFACE_DESC.
nun möchte ich die "eigentliche" surface an GetBackBuffer übergeben, damit diese "der back biuffer ist". mit einer methode der Klasse (Update) aktualisiere ich nun z.b. die surface desc.
ich weiß aber immer noch nicht, warum es nicht funzt... *heul*
@Knuddlbaer
das mit der funktion hab ich auch schon versucht, und ich bekam wieder einen runtime error...
-
Na vllt. lässt Du Dich auch mal dazu ab etwas fachliches dazu zu schreiben und lässt mich nicht dumm sterben.
Wir haben eine Klasse mit der membervariablen:
IDirect3DSurface8 * m_pIDirect3DSurface .
Benötigt wird IDirect3DSurface8 ** .
Wenn ich mich nicht täusche erreicht man dies mit &m_pIDirect3DSurface;
Mir fehlt die Kentniss wieso dies nicht passt und würde es gerne erfahren.Sein Code soll einen Zeiger auf einen Zeiger des Types IDirect3DSurface8 zurückgeben.
Warum
IDirect3DSurface8 * Surface::GetSurface() ; & SurfaceClass.GetSurface() ;
nicht geht sollte mittlerweile klar geworden sein. Wurde ja mehrmals in beiden Beiträgen erläutert. Tetris Fan hat sich an das Forum gewendet weil er eine Hilfestellung bekommen möchte. Ein Überhebliches "Denk nach dann weist Du es" zeugt nicht gerade von Hilfestellung. Im moment bist Du für mich nur ein Quacksalber der sich nicht mal die Beiträge richtig durchliest. Ich würde mich aber freuen wenn Du mir z.B. erklärst wieso
IDirect3DSurface8 ** Surface::GetSurface() { return &m_pIDirect3DSurface; }
nicht Funktioniert. Ich möchte ja auch noch was lernen
-
@Knuddlbaer
das mit der funktion hab ich auch schon versucht, und ich bekam wieder einen runtime error...Ich bin mir sicher das sich TGGC zu der Sache mal äußert und wie beide etwas über diese Problematik lernen werden
-
Dann erkläre doch mal, was genau dieses Stück machen soll:
m_pIDirect3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_pSurface[i].GetSurface())
Bye, TGGC
-
HRESULT IDirect3DDevice8::GetBackBuffer(UINT uBackBuffer // Zu ermittelnden Back Buffer D3DBACKBUFFER_TYPE Type // unwichtig, muss D3DBACKBUFFER_TYPE_MONO sein IDirect3DSurface8 ** pBuffer // Die Surface, in der die Funktion den ermittelten Back Buffer speichert
);
Ich würde also sagen:
Es gibt da ein Array von Surface Obejkten die hier in einer Schleife abgearbeitet werden sollen. Und zwar sollen alle bestehenden Objekte mit GetBackBuffer abgearbeitet werden. Ob dies nun so Sinn macht oder nicht kann man nur aus dem gesammtprojekt ermitteln.
Wenn Du auf das **&**m_pSurface[i].GetSurface() hinauswillst:
Lies mal die Beiträge
-
genau, danke, der sinn ist es, ein array von Surface objekten zu haben, die u.a. wie bereits 10 mal gesagt (nicht böse gemeint...) das IDirect3DSurface8 Interface beinhalten und so einfach und schnell zugriff auf die in eben dieser schleife ermittelnten backjbuffer zu ermöglichen.
das selbe hjabe ich auch vor bei meiner textur klasse, bloß0, dass es da die einzelnen mip levels und nicht die back buffer sind, die ich ermitteln will. das hat den zweck, dass ich auch einfach und schnell auf surfaces rendern kann, denn meine Surface klasse enthält auch ein ID3DXRenderToSurface Objekt.
@TGGC
diese zeile bezweckt auch wie schon achtzig mal gesagt, dass das in der Surface klasse enthaltene interface an getbackbuffer übergeben wird, sodass diese surface den backbuffer enthält!
-
Wenn das mit der "globalen" Variable klappt (pfui is das, da hat TGGC recht
Wenn es aber mit return &.... nicht geht gehe ich davon aus das Du
eine Änderung an der Variablen machst wärend der Laufzeit.
Beispiel:#include <iostream> class foo { int * i; int b; public: // Belegen des Speicherbereiches foo(){i = new int; *i = 12;} ~foo(){} // Gibt speicher frei und setzt andere Adresse void foobar(){delete i;i = &b;} // <-- Tut was was es nich tun darf :clown: // Gibt zeiger auf Zeiger zurück int ** bar(){return &i;} }; int main() { // @TGGC hierauf zielt meine Lösung ab: foo t; int ** i = t.bar(); // Zurückgeben eines Zeiger auf Zeiger des Typs int mit hilfe von & int* std::cout<<**i; // Nehmen wir an die API speichert die Adresse int * pi = *i; // Irgendwas ändert nun aber die Adresse in Deinem Objekt t.foobar(); // Und die API will nun darauf zugreifen. *pi = 12; // crascht weil in der Klasse *i freigegeben wurde und Adresse ungültig }
-
Tetris Fan schrieb:
diese zeile bezweckt auch wie schon achtzig mal gesagt, dass das in der Surface klasse enthaltene interface an getbackbuffer übergeben wird, sodass diese surface den backbuffer enthält!
Unsinn, der letzte Parameter ist ein Rückgabewert. Das bedeutet, du möchtest einen Member ändern. Jeder Code, der private Attribute auf diese Art modifiziert, ist ein Hack und gehört gelöscht.
@knuddlbär: return &... geht grundsätzlich, aber siehe deine eigene Anmerkung.
-
Ahhh..
GetBuffer erwartet hier also eine Adresse in die eine Rückgabe übergeben wird ?
Das bringt etwas Licht ins Dunkle und macht die vorgehensweise wirklich fragwürdigDemnach würde das Surface das die Klasse verwaltet von GetBackBuffer geliefert ?
Dann wäre eine lokale Variable zum befüllen wichtig die dann mit setirgendwas in die Klasse eingetragen wird !?
(Na siehste geht doch
Übrigens ist es nicht ungewöhnlich referenzen und zeiger zu liefern:
class t
{
std::string Name; // wird irgendwie gefülltconst std::string & Name(); // Gibt Name zurück
};Hier hilft das const die Rückgabe sauber zu halten. Du kannst nich immer eine Kopie mitgeben
*mal an TGGC übergeb, nu wird Ihnen geholfen
*
-
@TGGC
öhm, ich will dich nicht beleidigen, aber ist das nicht das gleiche??
@Knuddlbaer
ja, das ist richtig, die surface in der klasse kjommt von getbackbuffr oder in der texturklasse von GetLevel (oder wie die funktion heist)
@all
Knuddlbaer sagte, dass ich eine lokale variable füllen solle und diese dann per Set methoden an meine klasse weitergeben solle:
Frage 1: Wie genau (nur zur sicherheit bitte ein kleines code eispiel)
frage 2: funktioniert das überhaupt? ich meine in DX kann man doch nciht einfach ein Interface dem anderen zuweisen, das gibt doch ehler, oder??