Я написал простой модуль на Haskell, который можно преобразовать в общую библиотеку:
{-# LANGUAGE ForeignFunctionInterface #-}
module Safe where
import Foreign.C.Types
add :: Int -> Int -> Int
add p q = p + q
hs_add :: CInt -> CInt -> CInt
hs_add a b = fromIntegral (add (fromIntegral a) (fromIntegral b))
foreign export ccall hs_add :: CInt -> CInt -> CInt
с помощью команды
ghc -O2 -dynamic -shared -fPIC -o libAdd.so Add.hs -lHSrts-ghc8.2.2
Следующая программа отлично работает:
#include <stdio.h>
#include <dlfcn.h>
#include <HsFFI.h>
#define _LIB_INIT
int main(int argc, char *argv[])
{
void* handle;
static char *argv_N[] = { NULL }, **argv_ = argv_N;
static int argc_ = 0;
handle = dlopen("./libAdd.so", RTLD_NOW);
if (!handle)
{
fprintf(stderr, "%s\n", dlerror());
return 12;
}
else
fprintf(stderr, "Successfully loaded library\n");
#ifdef _LIB_INIT
void (*hs_init_l)(int *argc, char **argv[]) = dlsym(handle, "hs_init");
hs_init_l(&argc_, &argv_);
#else
hs_init(&argc_, &argv_);
#endif
int (*hs_add)(int a, int b) = dlsym(handle, "hs_add");
if (!hs_add)
{
fprintf(stderr, "Unable to load func : %s\n", dlerror());
return 3;
}
else
fprintf(stderr, "Successfully loaded function\n");
int a=8, b=12;
printf("%d + %d = %d\n", a, b, hs_add(a, b));
dlclose(handle);
return 0;
}
когда я скомпилирую с
ghc --make -no-hs-main -optc-O test.c -o test
Однако, если я уберу строку, определяющую _LIB_INIT
, я получу
Successfully loaded library
Successfully loaded function
newBoundTask: RTS is not initialised; call hs_init() first
Другими словами, если я вызываю hs_init
из общей библиотеки, это работает, но если я называю это статически связанной копией, функция hs_add
не распознает ее.
В чем разница между ними?