Zeiger auf Klasse unter 64 bit in DWORD



  • Ich habe eine Methode von der ein Parameter vom Typ DWORD ist. Beim Aufruf dieser Funktion gibt es einen Cast auf einen Zeiger, der auf eine Klasse verweist. Unter Win32 ist das alles kein Problem. Bei Win64 kommen folgende Warnungen:

    warning C4311: "Typumwandlung": Zeigerverkürzung von "Foo *" zu "DWORD"
    warning C4302: "Typumwandlung": Verkürzung von "Foo *" in "DWORD"

    Nun könnte man die 64Bit-Warnungen ausschalten, was mich aber auch nicht weiterbringt. Wie castet man das vernüftig?



  • AndyDD schrieb:

    Wie castet man das vernüftig?

    Um, gar nicht? Wieso musst du einen Pointer in einen DWORD casten?



  • dot schrieb:

    AndyDD schrieb:

    Wie castet man das vernüftig?

    Um, gar nicht? Wieso musst du einen Pointer in einen DWORD casten?

    Weil die Funktion die Zeigeradresse als DWORD braucht. Ich hab das Teil nicht geschrieben, ist ein Third-Party-Bibliothek und Support gibts da keinen mehr.



  • Der Typ mit der richtigen Größe dafür ist DWORD_PTR .



  • AndyDD schrieb:

    dot schrieb:

    AndyDD schrieb:

    Wie castet man das vernüftig?

    Um, gar nicht? Wieso musst du einen Pointer in einen DWORD casten?

    Weil die Funktion die Zeigeradresse als DWORD braucht. Ich hab das Teil nicht geschrieben, ist ein Third-Party-Bibliothek und Support gibts da keinen mehr.

    Dann funktioniert das unter 64-Bit einfach net... 😉



  • dot schrieb:

    Dann funktioniert das unter 64-Bit einfach net... 😉

    Kann man so nicht sagen. Es handelt sich ja um Compilerwarnungen. Ich hab jetzt mal unter Win64 die Lib eingebunden und die entsprechenden Funktionen aufgerufen. Es funktioniert, jedoch sollte man diese Warnungen weitestgehend abstellen, da man sonst ein undefiniertes Verhalten bekommen kann.



  • Doch, das kann man sehr wohl einfach so sagen; du castest einen Zeiger in einen 32-Bit Wert, das ist UB und fertig. Du bekommst nich erst UB wegen der Warnungen, der Compiler gibt dir die Warnungen, weil du UB hast. Wenn du die Warnungen deaktivierst, hast du trozdem noch UB; wenn das bei dir "funktioniert", dann ist das einfach nur Glück...



  • Die allgemeine Lösung für so etwas ist eine bijektive Abbildung zwischen Zeigern und den DWORD s für die Schrottbibliothek zu finden. Ein Cast ist bei 64-bit nicht bijektiv, scheidet also von vornherein aus. Man könnte DWORD s generieren und sich merken, welcher Zeiger dazu gehört. Ich meine ungefähr so etwas:

    std::map<void *, DWORD> to_dword;
    std::map<DWORD, void *> from_dword;
    


  • Es geschehen doch noch Zeichen und Wunder. Habe den Source für die DLL gefunden. Habe die DWORDs gegen QWORDs ausgetauscht. Jetzt kann man da auch einen 64Bit-Zeiger da reincasten.



  • TyRoXx schrieb:

    Der Typ mit der richtigen Größe dafür ist DWORD_PTR .

    😉

    Nur so aus interesse: Wenn du schon die kaputte lib fixen tust, wieso dann nicht einfach gleich einen Pointer übergeben?



  • dot schrieb:

    TyRoXx schrieb:

    Der Typ mit der richtigen Größe dafür ist DWORD_PTR .

    😉

    Nur so aus interesse: Wenn du schon die kaputte lib fixen tust, wieso dann nicht einfach gleich einen Pointer übergeben?

    Wenn da vorher ein DWORD stand, gehe ich mal davon aus, dass man da nicht unbedingt einen Zeiger übergeben muss.



  • dot schrieb:

    TyRoXx schrieb:

    Der Typ mit der richtigen Größe dafür ist DWORD_PTR .

    😉

    Nur so aus interesse: Wenn du schon die kaputte lib fixen tust, wieso dann nicht einfach gleich einen Pointer übergeben?

    Hmm, da haste eigentlich Recht. Hat jetzt DWORD_PTR unter Win64 definitiv 8 Byte? Oder soll da uintptr_t rein?



  • Wenn es ein vom nutzer gewählter wert sein kann, zb. für callbacks im c-style, dann ist eher void* oder eben DWORD_PTR oder uintptr_t angebracht. Ein zeiger ist unter win 64bit 8*8 bit lang, ebenso ist es uintptr oder vergleichbares aus der winapi wie long_ptr und dword_ptr.



  • roflo schrieb:

    Wenn es ein vom nutzer gewählter wert sein kann, zb. für callbacks im c-style, dann ist eher void* oder eben DWORD_PTR oder uintptr_t angebracht. Ein zeiger ist unter win 64bit 8*8 bit lang, ebenso ist es uintptr oder vergleichbares aus der winapi wie long_ptr und dword_ptr.

    Ja, es ist eine Callback-Funktion. Jedoch gibt's zwei Parameter. Der eine ist immer ein Zeiger auf eine Klasse, der andere kann auch ein Zeiger auf einen DWORD oder eben auch auf eine Klasse sein.



  • @AndyDD
    Ja, ein DWORD_PTR ist mindestens so gross wie ein Zeiger.
    Und mindestens so gross wie ein DWORD .
    signed/unsigned ist gleich wie bei DWORD , also unsigned .

    Das trifft übrigens auf alle XXX_PTR bzw. xxxptr_t Typen zu.

    Also die üblichen Eigenschaften eines XXX_PTR sind:
    * Grösse ist max(sizeof(XXX), sizeof(void*))

    • signed wenn XXX signed ist, unsigned wenn XXX unsigned ist

    Und typischerweise wählt man für XXX einfach das was man "sonst" verwendet hätte. Bei Portierung von Software von 32 auf 64 Bit also üblicherweise das was vorher verwendet wurde.
    Daher gibt es auch so viele verschiedene XXX_PTR , z.B. eben DWORD_PTR , INT_PTR , UINT_PTR , LONG_PTR , ULONG_PTR .



  • hustbaer schrieb:

    @AndyDD
    Ja, ein DWORD_PTR ist mindestens so gross wie ein Zeiger.
    Und mindestens so gross wie ein DWORD .
    signed/unsigned ist gleich wie bei DWORD , also unsigned .

    Das trifft übrigens auf alle XXX_PTR bzw. xxxptr_t Typen zu.

    Also die üblichen Eigenschaften eines XXX_PTR sind:
    * Grösse ist max(sizeof(XXX), sizeof(void*))

    • signed wenn XXX signed ist, unsigned wenn XXX unsigned ist

    Und typischerweise wählt man für XXX einfach das was man "sonst" verwendet hätte. Bei Portierung von Software von 32 auf 64 Bit also üblicherweise das was vorher verwendet wurde.
    Daher gibt es auch so viele verschiedene XXX_PTR , z.B. eben DWORD_PTR , INT_PTR , UINT_PTR , LONG_PTR , ULONG_PTR .

    Vielen Dank für deine Ausführungen. DWORD gegen QWORD getauscht funktioniert erst mal. Das würde jetzt im Umkehrschluss bedeuten, dass ich unter 64 bit einen DWORD_PTR nehmen kann und der dann auch die Zeigeradresse auf eine Klasse aufnehmen kann?



  • Ja.


Log in to reply