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 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.
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
In Ubuntu 12.04, I have jdk7 from sun/oracle installed. When locate jni.h, it prints multiple locations
/usr/lib/jvm/java-6-openjdk-amd64/include/jni.h
/usr/lib/jvm/jdk1.7.0_07/include/jni.h
...
In the header file generated by JDK, there is include <jni.h>, and currently it complains
fatal error: jni.h: No such file or directory.
In my Makefile, there is no specification of locations where jni.h is. And I am asking if possible to configure certain system parameter to make path of jni.h (say, /usr/lib/jvm/jdk1.7.0_07/include/jni.h) to be known when being compiled.
You have to tell your compiler where is the include directory. Something like this:
gcc -I/usr/lib/jvm/jdk1.7.0_07/include
But it depends on your makefile.
It needs both jni.h and jni_md.h files, Try this
gcc -I/usr/lib/jvm/jdk1.7.0_07/include \
-I/usr/lib/jvm/jdk1.7.0_07/include/linux filename.c
This will include both the broad JNI files and the ones necessary for linux
Installing the OpenJDK Development Kit (JDK) should fix your problem.
sudo apt-get install openjdk-X-jdk
This should make you able to compile without problems.
I usually define my JAVA_HOME variable like so:
export JAVA_HOME=/usr/lib/jvm/java/
Therein are the necessary include files. I sometimes add the below to my .barshrc when I compile a lot of things that need it.
Use the following code:
make -I/usr/lib/jvm/jdk*/include
where jdk* is the directory name of your jdk installation (e.g. jdk1.7.0).
And there wouldn't be a system-wide solution since the directory name would be different with different builds of JDK downloaded and installed. If you desire an automated solution, please include all commands in a single script and run the said script in Terminal.
Setting JAVA_INCLUDE_DIR to where jni.h is located should solve your problem (setting CPPFLAGS did not work for me)
Assuming it is /usr/lib64/java/include;
export JAVA_INCLUDE_DIR=/usr/lib64/java/include
For me it was a simple matter of being sure to include the JDK installation (I'd only had the JRE). My R CMD javareconf output was looking like:
Java interpreter : /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Java version : 1.8.0_191
Java home path : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java compiler : not present
Java headers gen.:
Java archive tool:
trying to compile and link a JNI program
detected JNI cpp flags :
detected JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm
gcc -std=gnu99 -I/usr/share/R/include -DNDEBUG -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c conftest.c -o conftest.o
conftest.c:1:17: fatal error: jni.h: No such file or directory
compilation terminated.
/usr/lib/R/etc/Makeconf:159: recipe for target 'conftest.o' failed
make: *** [conftest.o] Error 1
Unable to compile a JNI program
JAVA_HOME : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java library path:
JNI cpp flags :
JNI linker flags :
Updating Java configuration in /usr/lib/R
Done.
And indeed there was no include file in my $JAVA_HOME. Very simple remedy:
sudo apt-get install openjdk-8-jre openjdk-8-jdk
(note that this is specifically intended to install the openJDK and not the one from Oracle)
Afterwards all is well:
Java interpreter : /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Java version : 1.8.0_191
Java home path : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java compiler : /usr/lib/jvm/java-8-openjdk-amd64/jre/../bin/javac
Java headers gen.: /usr/lib/jvm/java-8-openjdk-amd64/jre/../bin/javah
Java archive tool: /usr/lib/jvm/java-8-openjdk-amd64/jre/../bin/jar
trying to compile and link a JNI program
detected JNI cpp flags : -I$(JAVA_HOME)/../include -I$(JAVA_HOME)/../include/linux
detected JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm
gcc -std=gnu99 -I/usr/share/R/include -DNDEBUG -I/usr/lib/jvm/java-8-openjdk-amd64/jre/../include -I/usr/lib/jvm/java-8-openjdk-amd64/jre/../include/linux -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c conftest.c -o conftest.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o conftest.so conftest.o -L/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server -ljvm -L/usr/lib/R/lib -lR
JAVA_HOME : /usr/lib/jvm/java-8-openjdk-amd64/jre
Java library path: $(JAVA_HOME)/lib/amd64/server
JNI cpp flags : -I$(JAVA_HOME)/../include -I$(JAVA_HOME)/../include/linux
JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm
Updating Java configuration in /usr/lib/R
Done.
Above answers give you a hardcoded path solution. This is bad on so many levels (java version change, OS change, etc).
Cleaner solution is to add:
JAVA_HOME = $(shell dirname $$(readlink -f $$(which java))|sed 's^jre/bin^^')
near the top of your makefile, then add:
-I$(JAVA_HOME)/include
To your include flags.
I am posting this because I ran into the same problem and spent too much time googling for wrong answers (I am building an app on multiple platforms so the build environment needs to be transportable).
None of the posted solutions worked for me.
I had to vi into my Makefile and edit the path so that the path to the include folder and the OS subsystem (in my case, -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux) was correct. This allowed me to run make and make install without issues.
In case you are on Ubuntu:
#X means 6,7,8...
apt install openjdk-X-jdk
I don't know if this applies in this case, but sometimes the file got deleted for unknown reasons, copying it again into the respective folder should resolve the problem.
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.