2015-01-22 18 views
9

Moja sprawa jest dość prosta: mam aplikację C++ i bibliotekę Haskell, i muszę wyeksportować z Haskella funkcję, która zwróci ciąg znaków C.Jaki jest właściwy sposób zarządzania przydzieloną pamięcią w obcym języku?

Problem jest, że ciąg C jest pierwotnie String, i aby uzyskać ciąg C z niego muszę przydzielić pamięci, które będą musiały być wyraźnie dealokowane (Haskell na free lub finalizerFree, jako dokumentacja dla newCString mówi) .

Co to jest dobry sposób na rozwiązanie tego problemu? W szczególności mam kilka uwag:

Idealnie chciałbym w jakiś sposób pozwolić na to, aby Gask wykonawczy Haskell je obsłużył, ale nie jestem pewien, jak to możliwe, aby wiedzieć, kiedy i kiedy pamięć jest nadal potrzebna strona obca. Czy to możliwe?

Jeśli nie, czy mogę po prostu zadzwonić do C free lub jest przechowywany CString utrzymywany przez środowisko wykonawcze Haskell? jeśli nie, to przypuszczam, że będę musiał wyeksportować Haskella do wersji free i zadzwonić do niego z zagranicy, zgadza się?

+1

'CString' to tylko alias dla gołego wskaźnika. Haskell nie będzie zarządzał pamięcią dla ciebie. Możesz zbudować [ForeignPtr] (https://hackage.haskell.org/package/base/docs/Foreign-ForeignPtr.html), jeśli chcesz, ale wymaga to trochę ostrożności. Za każdym razem, gdy używasz wskaźnika, musi on być całkowicie zawarty w wywołaniu ['withForeignPtr'] (https://hackage.haskell.org/package/base/docs/Foreign-ForeignPtr.html#v:withForeignPtr). – Rufflewind

+0

Jeśli ciąg nie jest zbyt duży (i nie zmienia się), lepiej byłoby skopiować go tak, aby jedna kopia była własnością strony zagranicznej, a druga kopia jest własnością środowiska wykonawczego Haskell. W przeciwnym razie możesz pomyśleć o tym, że obce strony przekazują własność tego ciągu do Haskella, tj. Strona obca nie zachowuje żadnych odniesień do pamięci, a jeśli musi coś zrobić, to wraca do Haskella, aby to zrobić. –

Odpowiedz

1

Musisz zwolnić ciąg znaków: jak mówisz, nie ma sposobu, w jaki Gask Haskell może wiedzieć, czy nadal jest potrzebny po stronie zagranicznej.

Haskell's free jest dokładnie równoważny z C free. Możesz zadzwonić albo ze strony, którą wolisz.

free :: Ptr a -> IO() 
free = _free 

foreign import ccall unsafe "stdlib.h free" _free :: Ptr a -> IO() 

nie sprawdzić, czy jest to nakazane przez raporcie Haskell + FFI uzupełnienia, ale ja myślę, że tak.

+1

Można również użyć 'pokeArray' z buforem przydzielonym za granicą, aby być po bezpiecznej stronie. – Rufflewind

+1

"Haskell's" free "jest dokładnie odpowiednikiem C's" free "- To może być prawda, ale opieka jest w porządku. Zobacz http://blog.haskell-exists.com/yuras/posts/malloc-free-and-ffi.html –

Powiązane problemy