Вызов Haskell из Java с C между - PullRequest
19 голосов
/ 01 ноября 2011

Возможно, это звучит как кошмар, но я бы очень хотел, чтобы это сработало.Я использую этот пример по большей части: Вызов C из Haskell и пытаюсь заставить это работать на Ubuntu.

Я запускаю это в Java:

package test;

public class JniTest {
    public native int fib(int x);
}

это в c после создания .h файла с javah: (test_JniTest.c)

#include "test_JniTest.h"
#include "Safe_stub.h"

JNIEXPORT jint JNICALL Java_test_JniTest_fib(JNIEnv * e, jobject o, jint f)
{
  return fibonacci_hs(f);
}

и затем для ссылки в haskell (перед заглушкой): (Safe.hs)

module Safe where

import Foreign.C.Types

fibonacci :: Int -> Int
fibonacci n = fibs !! n
    where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral

foreign export ccall fibonacci_hs :: CInt -> CInt

и вот что я пытаюсь скомпилировать:

ghc -c -O Safe.hs

с последующим:

ghc -shared -o libTest.jnilib -optc-O test_JniTest.c -I / usr / lib / jvm / java-6-sun-1.6.0.26 / include -I / usr / lib / jvm / java-6-sun-1.6.0.26 / include / linux

, и я получаю эту ошибку:

/ usr / bin / ld: test_JniTest.o: перемещение R_X86_64_PC32 противнеопределенный символ «fibonacci_hs» нельзя использовать при создании общего объекта;перекомпиляция с -fPIC / usr / bin / ld: окончательная ссылка завершилась неудачно: неверное значение collect2: ld вернул 1 состояние выхода

Я не специалист по переменным токам в любом случае и понятия не имею, что с этим делать,Я пытался компилировать разными способами с -fPIC, но продолжал получать ту же ошибку.Есть идеи, что я могу делать не так?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 04 июня 2012

Хотя я довольно много ответил на этот вопрос здесь: Связь между Java и Haskell , поскольку эта проблема больше касается самой ошибки, я добавлю подробности об этом здесь.Проблема связана с тем, что Haskell не очень хорошо поддерживает разделяемые библиотеки, в то время как Java требует их. Плагины для зданий в виде общих библиотек Haskell дает нам такую ​​возможность и обходные пути:

В принципе вы можете использовать -shared без -dynamic на этапе компоновки.Это будет означать статическое связывание всех базовых библиотек с вашей новой общей библиотекой.Это сделало бы очень большую, но автономную общую библиотеку.Однако для этого необходимо, чтобы все статические библиотеки были собраны с -fPIC, чтобы код был пригоден для включения в общую библиотеку, а мы сейчас этого не делаем.

Если мы снова используем ldd дляпосмотрите на libfoo.so, который мы сделали, мы заметим, что в нем отсутствует зависимость от библиотеки rts.Это проблема, которую нам еще предстоит решить, поэтому на данный момент мы можем сами добавить зависимость:

$ ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so \
 -lHSrts-ghc6.11 -optl-Wl,-rpath,/opt/ghc/lib/ghc-6.11/

Это обходной путь, потому что он требует, чтобы мы знали версиюБиблиотека rts во время сборки.

2 голосов
/ 02 ноября 2011

Если ваша цель состоит в том, чтобы на самом деле что-то сделать (а не просто поиграться с JNI), я предлагаю решить эту проблему как проблему RPC для садового разнообразия и использовать для этого один из многих фреймворков / протоколов:

Буферы протокола от Google

Комиссионные от Facebook

Avro (ну, в основном это проводной протокол)

Из того, что вы пытаетесь сделать, Thrift может быть вашим лучшим выбором, поскольку он описывает полный стек RPC клиент / сервер, но я уверен, что любой из них в значительной степени будет работать через простой сокет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...