que - Llamando a Haskell desde Java con C en medio
evaluacion de los lenguajes de programacion (2)
Probablemente esto parezca una pesadilla, pero realmente me gustaría hacer que esto funcione. Estoy usando este ejemplo en su mayor parte: Llamando a C desde Haskell y estoy tratando de hacer que esto funcione en Ubuntu.
Estoy ejecutando esto en java:
package test;
public class JniTest {
public native int fib(int x);
}
esto en c después de crear el archivo .h con 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);
}
y luego como referencia en haskell (antes del código auxiliar): (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
Y esto es lo que estoy tratando de compilar con:
ghc -c -O Safe.hs
seguido por:
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
y estoy recibiendo este error:
/ usr / bin / ld: test_JniTest.o: la reubicación R_X86_64_PC32 contra el símbolo no definido `fibonacci_hs ''no se puede usar al crear un objeto compartido; recompile con -fPIC / usr / bin / ld: error en el enlace final: valor incorrecto collect2: ld devolvió 1 estado de salida
No soy un experto en CA de ninguna manera y no tengo idea de qué hacer al respecto. Intenté compilar varias formas con -fPIC, pero seguí recibiendo el mismo error. ¿Alguna idea de lo que podría estar haciendo mal?
¡Gracias!
Aunque he respondido bastante a esta pregunta aquí: Comunicación entre Java y Haskell , ya que este problema es más sobre el error en sí, agregaré los detalles para eso aquí. El problema se debe a que Haskell no admite bibliotecas compartidas muy bien, mientras que Java las requiere. Los complementos de edificios como las librerías compartidas de Haskell nos dan esta perspectiva y solución:
En principio, puede utilizar -shared sin -dynamic en el paso de enlace. Eso significaría vincular estáticamente todas las bibliotecas base a su nueva biblioteca compartida. Esto haría una biblioteca compartida muy grande, pero independiente. Sin embargo, eso requeriría que todas las bibliotecas estáticas se hayan construido con -fPIC para que el código sea adecuado para incluir en una biblioteca compartida y no lo hacemos en este momento.
Si usamos ldd otra vez para ver el archivo libfoo.so que hemos hecho, notaremos que falta una dependencia en la biblioteca rts. Este es un problema que aún no hemos resuelto, así que por el momento solo podemos agregar la dependencia a nosotros mismos:
$ ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so / -lHSrts-ghc6.11 -optl-Wl,-rpath,/opt/ghc/lib/ghc-6.11/
Esta es una solución porque requiere que conozcamos la versión de la biblioteca rts en el momento de la compilación.
Si su objetivo es realmente hacer algo (en lugar de solo jugar con JNI), sugiero abordar esto como un problema de RPC de variedad de jardín y utilizar uno de los muchos marcos / protocolos para ello:
Avro (bueno esto es principalmente un protocolo de conexión)
Por lo que está tratando de hacer, Thrift podría ser su mejor apuesta, ya que describe una pila de RPC cliente / servidor completa, pero estoy bastante seguro de que cualquiera de ellos funcionaría en un simple zócalo.