Expose Haskell-функции через иностранный экспорт ccall не удается для CStrings - PullRequest
3 голосов
/ 22 июля 2011

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

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

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();
}

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

1 Ответ

2 голосов
/ 22 июля 2011

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

Модуль My 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

EDIT: просто предположение, но, возможно, импорт CString сработает, если вы укажете {-# LANGUAGE Haskell98, ForeignFunctionInterface #-}

...