I'm having troubles with compiling a standalone library for use by Java (with C++ inbetween).
There is a program in Haskell exporting one function that processes some text and returns it.
The program in Haskell needs some external data (binary file). I'm 'compiling it in' with the help of file-embed package.
When I started the compilation with:
$ ghc -fPIC -dynamic -c -O --make MyModule.hs
It throws the error:
MyModule.hs:239:15:
Dynamic linking required, but this is a non-standard build (eg. prof).
You need to build the program twice: once the normal way, and then
in the desired way using -osuf to set the object file suffix.
This is the place where I use file-embed.
So I tried the proposed approach (compiling twice, changing suffixes):
$ ghc -fPIC -c -O --make MyModule.hs
$ ghc -osuf d.o -fPIC -dynamic -c -O --make MyModule.hs
$ javac -cp javacpp.jar MyModule.java
$java -jar javacpp.jar -Dcompiler.path=ghc -Dcompiler.output.prefix="-optc-O3 -Wall MyModule.d.o -dynamic -fPIC -shared -lstdc++ -lHSrts-ghc7.6.3 -o " -Dcompiler.linkpath.prefix2="-optl -Wl,-rpath," MyModule
And now I'm getting an error that I don't understand:
/usr/bin/ld: MyModule.d.o: relocation R_X86_64_PC32 against undefined symbol `{Directory_with_code}zi{Some_module}_{Some_module}_con_info' can not be used when making a shared object; recompile with -fPIC
Can anyone explain it to me and give some tips on how to solve it?
Just a guess, but maybe you need to different version of HSrts-ghc-7.6.3 since this is a "non-standard" build.
Related
I convert C++ to Java using swig.
I use g++ for creating DLL and compiling.
swig -c++ -java -package preprocessor Point.i
g++ -c -std=c++11 Point.cpp Point_wrap.cxx -I E:\ProgramFiles\jdk\include -I E:\ProgramFiles\jdk\include\win32
g++ -shared Point_wrap.o Point.o -o point.dll
I don't have any errors while compilation and creating dll.
So when I put generated java files and dll to my project I have an UnsatisfiedLinkError when I create new object. It appears only when I use Windows 8.1 x86. On x64 version everything works fine.
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: preprocessor.PointClassJNI.new_Point__SWIG_0()J
at preprocessor.PointClassJNI.new_Point__SWIG_0(Native Method)
at preprocessor.Point.<init>(Point.java:78)
at GUI.FileWorker.fileParser(FileWorker.java:45)
at GUI.MainWindow$2.actionPerformed(MainWindow.java:139)
This is what swig generates and where error occurs when I create point = new Point();
public Point() {
this(PointClassJNI.new_Point__SWIG_0(), true);
}
Maybe someone had this problem. I will be very grateful for any help!
Finally I find the solution in this question.
Just need to add -Wl,--add-stdcall-alias to my .bat file when I create dll.
swig -c++ -java -package preprocessor Point.i
g++ -c -std=c++11 Point.cpp Point_wrap.cxx -I E:\ProgramFiles\jdk\include -I E:\ProgramFiles\jdk\include\win32
g++ -shared Point_wrap.o Point.o -Wl,--add-stdcall-alias -o point.dll
rkapl, thank you for respond!
I'm trying to use AES via the Crypto++ package from Java. Therefore I have two native methods encrypt and decrypt in my Java code which are then wrapped by C in order to access the C++ methods.
Running my C++ program from the command line works, but calling it from Java via JNI fails with an undefined symbol error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/yves/temp/lib/libCI3CppEncryptionTools.so: /home/yves/temp/lib/libCI3CppEncryptionTools.so: undefined symbol: _ZTIN8CryptoPP6FilterE
I'm compiling it via:
g++ -c -Icryptopp562 -O3 -fwhole-program -fdata-sections -ffunction-sections -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp -Lcryptopp562 -lcryptopp
gcc -I${JAVA_HOME}/include -O3 -fwhole-program -fdata-sections -ffunction-sections -Wall -shared -fPIC -o libCI3CppEncryptionTools.so CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -Wl,--gc-sections
So first the C++ part and then combined with the C wrapper. -fdata-sections, -ffunction-sections and -Wl,--gc-sections were my attempt to strip dead code because I thought maybe JNI does not like unused or unreferenced code.
I checked if the symbol is undefined by using:
nm lib/libCI3CppEncryptionTools.so | grep _ZTIN8CryptoPP6FilterE
U _ZTIN8CryptoPP6FilterE
And yes, it is. But why is my C++ command line program working? Checking this yields the same result.
I also looked the symbol up:
c++filt _ZTIN8CryptoPP6FilterE
typeinfo for CryptoPP::Filter
The header for CryptoPP::Filter is included. I'm curious why it says U when checking for the symbol.
Does anyone have any idea what could cause the problem or where to look next to solve the problem? Any hints/insights are highly welcome!
Compile your CI3CppEncryptionTools.c first, then link its .o into the .so. You are linking the .c
Edit: Statically link your cryptocpp library into your shared library via : -Wl,--whole-archive libcryptocpp.a -Wl,--no-whole-archive
gcc -I${JAVA_HOME}/include -O3 -fwhole-program -fdata-sections -ffunction-sections -Wall -shared -fPIC -o libCI3CppEncryptionTools.so CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -Wl,--whole-archive libcryptocpp.a -Wl,--no-whole-archive -Wl,--gc-sections
I always forgot to link the Crypto++ library in the second step (actually I did it in the first step, which was complete nonsense). Those two commands compile the library a-ok!
g++ -c -Icryptopp562 -O3 -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp
gcc -I${JAVA_HOME}/include -O3 -shared -fPIC -o libCI3CppEncryptionTools.so CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -lcryptopp
I've got a Java project which depends on a native library. I'm using SWIG to build the native library, which works fine on *nix systems. I'm trying to get it to compile now on Windows using the mingw 64 bit toolchain and SWIG. It will compile and I can get the jnilib packaged appropriately (i.e. the same way as I'm doing it on other platforms) but when I try to load the library in the Java code I get:
Exception in thread "main" java.lang.UnsatisfiedLinkError: ... .jnilib: Can't find dependent libraries
and then it has the trace on the java side. Clearly I'm not linking something properly but I'm not sure what. Here's the relevant part of my compile commands:
swig -java -package cStopPow -c++ StopPow.i
x86_64-w64-mingw32-g++ -I"C:/Progra~1/Java/jdk1.7.0_25/include/" -I"C:/Progra~1/Java/jdk1.7.0_25/include/win32/" -std=c+
+11 -O3 -I"C:/MinGW/include/boost/math/" -c ../src/StopPow.cpp ../src/StopPow_SRIM.cpp ../src/StopPow_LP.cpp ../src/Stop
Pow_BetheBloch.cpp ../src/StopPow_AZ.cpp ../src/PlotGen.cpp ../src/AtomicData.cpp StopPow_wrap.cxx
x86_64-w64-mingw32-g++ -shared -lmingw32 -mconsole StopPow_wrap.o StopPow.o StopPow_SRIM.o StopPow_LP.o StopPow_BetheBlo
ch.o StopPow_AZ.o PlotGen.o AtomicData.o -o libcStopPow.jnilib
Why the output is libcStopPow.jnilib? I think it must a dll file
I use SWIG 2.0.10, Oracle JDK 1.7.0_40 and mingw 64 from http://nuwen.net/ with the Examples\java\simple. I do the following in cmd (I set JAVA_HOME correctly)
swig -java -c++ example.i
g++ -Wall -Wl,--kill-at -I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" -shared -s -o example.dll *.c *.cxx
java -cp . runme
It works as expected
I'm trying to follow the SWIG Java example located here. This example uses cygwin for compilation. I would like to pass the compiler an alredy compiled dll, test.dll, instead of a C source file. The SWIG.org example uses C source. I attempted to pass the test.dll(compiled C source) and then example.dll to the 3rd command but I get an error "test.dll: no such file or directory". The SWIG.org example's 3rd command creates the example.dll based on example.c. How can I create example.dll so that it uses test.dll instead of example.c?
Is there a way to accomplish this within the context of this example?
My Attempt without C Source, just dll:
$ swig -java example.i
$ gcc example_wrap.c -I/c/jdk1.6.0_30/include -I/c/jdk1.6.0_30/include/win32
$ gcc -shared example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o test.dll example.dll
SWIG.org Example Code:
$ swig -java example.i
$ gcc **-c example.c** example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32
$ gcc -shared example.o example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o example.dll
You need to pass test.dll to the last command, which links your program, rather than the second, which just compiles the example_wrap.c source file. (The -c option tells gcc to compile only.)
Note that the ordering of objects and DLLs on the link line is important. DLLs should come after anything that uses them.
What compiler (I'm using gcj 4.x) options should I use to generate an "exe" file for my java application to run in windows?
To compile the Java program MyJavaProg.java, type:
gcj -c -g -O MyJavaProg.java
To link it, use the command:
gcj --main=MyJavaProg -o MyJavaProg MyJavaProg.o
and then linking to create an executable mycxxprog.exe
g++ -o mycxxprog.exe mycxxprog.o