2015-05-14 2 views
3

Я пытаюсь привязать к функции C, которая возвращает структуру (по значению). Я знаю, что могу обернуть его вручную, используя FFI, но не могу понять, как коаксировать c2hs в генерирование правильного кода. Кажется, моя функция возвращает указатель.Возвращение пустой структуры из C в Haskell в c2hs

Вот простой пример:

module Point where 

#c 
struct point { 
    int x; 
    int y; 
}; 

struct point get_zero(void); 
#endc 

data Point = Point { x :: Int, y :: Int } 

instance Storable Point where 
    sizeOf _ = {#sizeof point#} 
    alignment _ = {#alignof point#} 
    peek p = point <$> liftA fromIntegral ({#get point.x #} p) 
        <*> liftA fromIntegral ({#get point.y #} p) 
    poke p s = do {#set point.x #} p (fromIntegral $ x s) 
        {#set point.y #} p (fromIntegral $ y s) 

{#pointer *point as PointPtr -> Point#} 

-- Causes error: 
{#fun get_zero as^{ } -> `Point'#} 

Ошибка:

c2hs: Errors during expansion of binding hooks: 

Point.chs:25: (column 28) [ERROR] >>> Missing "out" marshaller! 
    There is no default marshaller for this combination of Haskell and C type: 
    Haskell type: Point 
    C type  : (Ptr()) 

ответ

4

Это не представляется возможным в настоящее время. Вы можете сделать обертку, которая возвращает результат по указателю:

void get_zero_wrapper(struct point* p) { 
    *p = get_zero(); 
} 

Заметим, что вы должны выделить пространство для структуры, например, используя alloca.

Существует proposal для поддержки передающих и возвращающих структур C по значению в FFI. Но вряд ли он будет реализован в ближайшем будущем, потому что он не получил достаточного внимания со стороны сообщества. Предложение нуждается в более тщательном проектировании, например. неясно, как он будет работать с другими языковыми функциями.

+0

Спасибо! Я также пытался выяснить, может ли c2hs автоматически создавать этот вид упаковки, я думаю, что ответ «нет». – sinelaw

+0

Посмотрел на ваше предложение - есть ли работа над этим? С «современными» C (C99) возвращающими малыми структурами часто является хорошим способом уменьшить крутизну указателей в API, было бы неплохо иметь поддержку для этого ... – sinelaw