2016-09-03 3 views
5

Рассмотрим Haskell тип данных, который выглядит как этотПопутный-структуры, как данные между C и Haskell через FFI

data MyData = MyData { arrInt :: [Int] , arrDouble :: [Double], arraySize :: N } 

Здесь N представляет размеры обоих массивов рекорд MyData.

Возможно ли передать этот (или какой-либо указатель «Haskell» объекта MyData) функции C, которая выглядит так.

int myfunc (int* a, double* b, int N) 

Я могу использовать FFI для вызова функций C прием и возврат простых datat-типа, такие как распашные, Int, Char и т.д. Но для более сложных типов я не знаю, что делать.

+1

Будет ли подпрограмма C модифицировать два массива? – chi

+0

@chi Нет. По крайней мере, не для приложений, которые я имею в виду. – smilingbuddha

ответ

4

Вы могли бы сделать что-то вроде этого:

import Foreign 
import Foreign.C 

myfunc :: MyData -> IO CInt 
myfunc d = 
    withArray (map fromIntegral $ arrInt d) $ \arr1 -> 
     withArray (map CDouble $ arrDouble d) $ \arr2 -> 
      c_myfunc arr1 arr2 (fromIntegral $ arraySize d) 

foreign import ccall safe "myfunc" 
    c_myfunc :: Ptr CInt -> Ptr CDouble -> CInt -> IO CInt 
+0

Интересно! Являются ли данные внутри «d» скопированы в отдельную соответствующую C-структуру, на которой работает c_myfunc? Или c_myfunc работает непосредственно на записи «d», как если бы это был тип C. Это было бы очень важно знать о производительности при работе с большими данными. – smilingbuddha

+0

Скопирован в отдельную структуру. В общем, представление Хеккелла наиболее сложных типов данных существенно отличается от C, поэтому передача данных в C и из C включает в себя много копий. Вы можете избежать этого в тех немногих случаях, когда вам не нужно выполнять обработку данных на одном из двух языков. В этом случае вы просто храните данные в формате языка, который выполняет обработку. – redneb

+0

@smilingbuddha Необходима копия. Макет памяти Haskell для '[Int]' не является смежным массивом, как в C. Обратите внимание, что если функция изменяет эти массивы, изменения не будут отражены в аргументе pure MyData. При необходимости можно заставить 'myfunc' вернуть новую обновленную' MyData'. – chi