Предоставление Haskell-функций через внешний вызов экспорта не удается для CStrings

Я сделал короткую программу на Haskell, которая предоставляет функции для C или Python. Читал на http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/ffi-ghc.html#ffi-library к письму, и это сработало для экспорта целых чисел.

Хотите экспортировать строки и сделали программу:

module Adder where

import CString

adder :: Int -> Int -> IO CString 
adder x y =  newCString(show(x+y))

foreign export ccall adder :: Int -> Int -> IO CString

Это нормально компилируется, когда я делаю: ghc adder.hs, но при связывании для создания dll в Windows происходит сбой.

ghc -shared -o adder.dll adder.o adder_stub.o StartEnd.o

Ошибка: adder.o:fake:(.text+0x11d): неопределенная ссылка на `__stginit_haskell98zm1zi1zi0zi1_CString_'

StartEnd.o скомпилирован из C-файла, который я скопировал с сайта haskell.org:

#include <Rts.h>
extern void __stginit_Adder(void);
void HsStart()
{
  int argc = 1;
  char* argv[] = {"ghcDll", NULL}; // argv must end with NULL
  // Initialize Haskell runtime
  char** args = argv;
  hs_init(&argc, &args);
  // Tell Haskell about all root modules
  hs_add_root(__stginit_Adder);
}
void HsEnd()
{
  hs_exit();
}

Что я должен сделать, чтобы иметь возможность экспортировать строки ??


person edward hage    schedule 21.07.2011    source источник
comment
Как примечание, я бы избегал стиля f(g(x)) и использовал либо f (g x), либо f $ g x, либо f . g $ x   -  person alternative    schedule 22.07.2011


Ответы (1)


Попробуйте импортировать Foreign.C.String вместо модуля CString. GHC должен распознать модуль и связать его с правильной библиотекой. В системе Linux при компиляции статики у меня была та же проблема, что и у вас (неопределенная ссылка). Когда я изменил этот импорт, оставив мне код ниже, все заработало.

Мой модуль Haskell (функции экспорта):

$ cat so.hs
module Adder where

import Foreign.C.String

adder :: Int -> Int -> IO CString 
adder x y =  newCString(show(x+y))

foreign export ccall adder :: Int -> Int -> IO CString

Мой основной файл C (который включает в себя всю работу по инициализации и удалению, не очень красиво, но это просто для обучения):

$ cat soMain.c
#include <Rts.h>
#include "so_stub.h"

extern void __stginit_Adder(void);

void main()
{
  char *str = NULL;
  int argc = 1;
  char* argv[] = {"ghcDll", NULL}; // argv must end with NULL
  // Initialize Haskell runtime
  char** args = argv;
  hs_init(&argc, &args);
  // Tell Haskell about all root modules
  hs_add_root(__stginit_Adder);

  // END INIT


  str = adder(1,2);
  printf("%s\n",str);

  // END MAIN START THE FINALIZERS
  hs_exit();


}

Мои команды:

$ ghc -c so.hs
$ ghc soMain.c so_stub.o so.o -o so -fforce-recomp
$ ./so
3

РЕДАКТИРОВАТЬ: Просто предположение, но, возможно, импорт CString будет работать, если вы укажете {-# LANGUAGE Haskell98, ForeignFunctionInterface #-}

person Thomas M. DuBuisson    schedule 21.07.2011
comment
Спасибо, это помогло. Также нужно было #include объект-заглушку, и тогда он отлично работал. - person edward hage; 22.07.2011
comment
Кстати, недавно я добавил пакет для автоматического экспорта функций haskell, его можно найти по адресу hackage. haskell.org/package/Hs2lib , даже если вы не хотите его использовать, может быть полезно посмотреть, как выглядит код FFI. (используйте -T для сохранения промежуточных файлов) - person Phyx; 27.07.2011