x64 (windows) pointer als 32bit handle (C functor)



  • Guten Morgen Leute,

    ich habe folgendes "Problem":

    Ich habe eine 64 bit Anwendung welche auf eine C-Api zurückgreift.
    Eine Api Funktion erwartet einen Function pointer. welcher ja sinngemäß "static" deklariert sein muss.!?

    typedef void (* PAdsNotificationFuncExConst)(const AmsAddr* pAddr, const AdsNotificationHeader* pNotification,
                                                 uint32_t hUser);
    

    diese funktionpointer stellt eine callback funktion dar, weche bei event aufgerufen wird, nun kann ich diese event registeren:

    .. new AdsNotification { route, symbolName, attrib, &NotifyCallback, 0xBEEFDEAD /* handle */ };
    
    

    dieser handle ist eine uint32_t typ, welcher ich mitgeben, damit beim aufruf callback user-data mit gebeben werden kann.

    ok gut, nun möchste ich aber einen Pointer eines Objects als userdata mitgeben, aber da ich mich ja in einer x64 umgebung befinde ist dieser 64bit statt mögliche 32 bit (userdate) groß.

    Habe ich nun irgendeine möglichkeit beim erzeugen von objekten die addresse auf max 32bit addresse zu begrenzen (new).

    Oder wie sage ich dieser statischen methode nun mit welche 64bit object das callback ausgelöst hat!?

    Danke, bin gespannt auf euere Antworten



  • Mit standard C++ wirst du leider nicht deine pointer beinflussen können (abgesehen vom placement new). Was du machen könntest ist eine map von uint32_t IDs zu erstellen, die jeder ID einen pointer zuweist. Damit handelst du dir natürlich neue Probleme ein: Wie generierst du performant die IDs? Multithreading? …

    Ansonsten ist es vermutlich mit betriebsystemspezifischen Mitteln möglich an 32 Bit pointer zu kommen. Unter Linux kann man mit mmap und dem flag MAP_32BIT sicherstellen, dass man solche pointer bekommt. Wie das unter anderen Betriebsystemen aussieht weiß ich nicht.



  • @Biolunar sagte in x64 (windows) pointer als 32bit handle (C functor):

    Mit standard C++ wirst du leider nicht deine pointer beinflussen können (abgesehen vom placement new). Was du machen könntest ist eine map von uint32_t IDs zu erstellen, die jeder ID einen pointer zuweist. Damit handelst du dir natürlich neue Probleme ein: Wie generierst du performant die IDs? Multithreading? …

    quais eine statische map welche meine ptr der objekte hält.. habe ich mir als notlösung auch gedacht danke. aber v. geht es ja doch eleganter? hmm



  • welcher ja sinngemäß "static" deklariert sein muss.!?

    Nein (was auch immer sinngemäß hier bedeuten soll)



  • @SoIntMan sagte in x64 (windows) pointer als 32bit handle (C functor):

    aber v. geht es ja doch eleganter? hmm

    Auf twinCAT 3 umsteigen?



  • @manni66 sagte in x64 (windows) pointer als 32bit handle (C functor):

    Auf twinCAT 3 umsteigen?

    Hi manni, ich verwende dies c-lib auf x64 gebuilded, trotzdem verwendet die ads.lib 32 bit user data :

    https://github.com/Beckhoff/ADS

    vergiss das mit dem "sinngemäß", wollt eine eine member -funktion als callback ptr übergeben was ja nich geh ...ohne dass sie zudem statisch is!?



  • Eine Alternative wäre vielleicht die Objekte z.B. in einem std::vector abzulegen und als Userdata einen Index in diesen zu verwenden. Das ist genau so effizient wie Pointer. Nachteil ist natürlich, dass die Objekte alle in dem Vector sein müssen.



  • Wenn die referenzierten Objekte dynamisch erzeugt und wieder freigegeben werden müssen kannst du eine sog. slot-map verwenden.
    Im Prinzip ist das eine Map die die (Integer-)Keys selbst vergibt. Dafür sind die Operationen alle recht schnell - Einfügen/Lookup/Löschen sind alle O(1).
    Darin kannst du dann z.B. Zeiger auf die Objekte speichern.

    Gibt's allerdings nicht fertig in der Standard-Library.
    Du müsstest dir entweder selbst eine Implementierung schreiben oder eine fertige suchen.

    Und natürlich: Falls dein Programm Threads verwendet musst du die Zugriffe auf die globale Datenstruktur (welche auch immer du dann verwendest) synchronisieren.



  • Guten Morgen,

    ja genau super Idee, genau so werde ich es umsetzen.. vielen Dank:)

    @hustbaer sagte in x64 (windows) pointer als 32bit handle (C functor):

    eine sog. slot-map verwenden.

    Noch eine kurze frage zu "statischen" Objektion. Wie sieht die lebenzeit einer statischen variable einer Klasse aus? sobald mind. ein objekt der Klasse erzeugt wird, wird diese angelegt. oder schon beim starten des Prozesses.!?

    Danke


  • Mod

    Statische Klassenvariablen sind verkappte statische globale Variablen und werden zusammen mit diesen beim Programmstart erzeugt. Die genaue Reihenfolge liegt zwischen kompliziert bis undefiniert.



  • @SoIntMan
    Google "static initialization order fiasco" wenn du mehr über das Thema wissen willst.

    Weil's zum Thema passt: Eine der einfachsten Lösungen dafür ist Meyers' Singleton:

    static Singleton& instance()
    {
         static Singleton s;
         return s;
    }
    

    Damit ist garantiert dass die Initialisierung von s genau beim ersten Aufruf von instance erfolgt. Und seit C++11 ist das ganze auch thread-safe.



  • Vielen dank , ich habe ja "nur" eine statische variable, da is die init- order erst mal wurst oder;)!?



  • Du hast in deinem ganzen Programm nur eine (dynamisch initialisierte) statische Variable? Nice.

    Aber egal.
    Ich würde es gleich "richtig" machen - zumindest so richtig wie einfach möglich. Also mit einem Meyers' Singleton.

    Re. "so richtig wie einfach möglich": Neben dem "static initialization order fiasco" gibt es natürlich auch noch das "static uninitialization order fiasco" bzw. "static destruction order fiasco". Und das wird durch Meyers' Singleton leider nicht gelöst.



  • Das wäre ein Thema gewesen, was hätte dringend verbessert werden müssen. Leider sind mal wieder viele andere Dinge dem vorgezogen worden, weil es eben so viel leichter ist.


Anmelden zum Antworten