Ich versuche, einen Haskell-Wrapper für eine C-Bibliothek zu erstellen. Die zugrunde liegenden Strukturen sind zu kompliziert, um sie als explizite Typen auszudrücken, und ich benutze sie eigentlich nur für den Übergang zwischen C-Funktionen. Daher verwende ich EmptyDataDecls
, damit GHC es für mich ausarbeitet.
Was ich brauche, ist ein Zeiger auf einen dieser Datentypen, aber wenn ich versuche, einen mit alloca
zu erstellen, beschwert er sich, dass die Daten nicht vom Typ Storable
sind. Zum Beispiel:
GHC kompiliert das nicht und sagt, dass es keine Instanz für Storable Struct
gibt. Ich könnte es selbst umsetzen:
Aber das ist nahe daran, den Zweck zu besiegen - ich will solche Dinge nicht definieren müssen, wenn es mir egal ist, was in der Struktur ist.
Ich habe bemerkt, dass ein Zeiger auf einen Zeiger gut funktioniert, weil die Klasse Ptr
Storable
ist. So kann ich erreichen, was ich anstrebe, indem ich peek
auf ptr
benutze, bevor ich get_struct
:
Das fühlt sich jedoch an wie ein Hack.
Gibt es eine Möglichkeit, leere Datendeklarationen als Storable
zu betrachten, ohne eine Instanz zu definieren?
Sie können nichts zuweisen, wenn Sie nicht wissen, wie groß es ist. Wird die Funktion ihr Argument einfach ignorieren? Dann geben Sie einen Nullzeiger ein. Andernfalls müssen Sie tatsächlich genügend Speicherplatz für die Struktur reservieren - schneiden Sie keine Ecken ab, indem Sie einen Nullbyte- oder Pointer-großen Puffer zuweisen, da dann die aufgerufene Funktion über das Ende Ihres Puffers hinaus schreibt und Speicher beschädigt.
>Beenden Sie entweder die Datendeklaration oder schreiben Sie eine speicherbare Instanz mit den richtigen Größen- und Ausrichtungswerten. Es gibt keine Möglichkeit, Größen- / Ausrichtungsdaten in irgendeiner Form zur Verfügung zu stellen.
Hier ist ein anderer Ansatz, der für Sie funktionieren könnte. Ich nehme an, dass Sie Zugriff auf alle C-Header-Dateien haben, die die Objekte definieren, die Sie zuordnen müssen. Wenn das stimmt, könnten Sie eine dünne Schicht C-Code schreiben, um die C-Objekte zuzuweisen und freizugeben. Ihr Haskell-Code kann dann diese C-Funktionen aufrufen, ohne dass der Haskell-Code jemals wissen muss, was sich hinter den Zeigern befindet. Haskell kann den freien Code auch automatisch aufrufen, wenn Haskells Garbage Collector weiß, dass die Objekte nicht mehr benötigt werden.