Using a compiled DLL in Java with SWIG and Visual Studio 2015 - java

I have a compiled DLL (C/C++) and I have to use it in Java. So I want to use SWIG to create a wrapper . I followed all the tutorials like:
How to create a DLL with SWIG from Visual Studio 2010
http://www.swig.org/Doc3.0/Java.html
SWIG JNI Interface with DLL and declarations only
But in all the examples no precompiled DLL and/or Java and/or Visual Studio (2015) were used. When using an own cpp file for the implementation (and don't use an external DLL, implementing the header) everything works fine (compile to a single DLL and calling from Java).
So what do I want: Having a precompiled DLL (example.dll), the header for that (example.h) and the SWIG header file (example.i). Compile everything to a "wrapper DLL", load this one in Java and accessing the precompiled DLL (example.dll).
My steps in detail:
New VS class library project
Add the h and i file
Add the custom build step for the i file (like in the example)
Java files and the example_wrap.cxx file is generated
Add the example_wrap.cxx, add Java includes and don't use precompiled headers
Compile example_wrap.cxx to example.lib (Is that right?)
Setting project settings like in the tutorials (no clr, add java-includes, no precompiled headers)
Now creating the whole project fails with linking error LNK2019 in example_wrap.obj.
Can someone help me?
What I also don't get: The result will be "example.dll". I have to use this DLL in Java (with System.load/loadLibrary). How can this SWIG DLL access the "original" example.dll with all the logic inside?
Using Python instead of Java results in the same failure (LNK2019 - unresolved external symbol).

Basically you need to "forward" the calls to the external library. I.e. import symbols from there into the wrapper library and link with the external DLL lib file.
If you do not have such a lib file for the DLL, you need to either create it (e.g. using some tool the create lib from the DLL), or load the external library/import symbols at runtime (LoadLibrary/GetProcAddress).

The answer from axalis was absolutly right. Here some details:
Add example.cpp
Load the precompiled DLL (example.dll) with LoadLibrary and save a reference
Load methods from there with GetProcAddress and save a reference for each method
Write an "implemantation" for each method where you just call the method loaded before
Compile and link everything to exampleWrap.dll and load this dll in the Java project

Related

Linux & Java: no native in java library path whereas it is there

I use JNI in my Java code to communicate with C++. The C++ code is compiled and stored in a native library that can be accessed by Java. On Windows, I use IntelliJ to run my code and added the folder that contains the native library to my -Djava.library.path. No issues here, my code runs just fine and is able to locate and work with the library.
My next step is to have it all working on a server with Linux. Here, I run into problems. Using GitHub, I pulled my code on the server, created new objects of my .cpp files and compiled it into a native.so library. Next, I call my experiment using
java -Djava.library.path=/home/usr/ILOG/CPLEX_Studio1210/cplex/bin/x86-64_linux:/home/usr/FSVRPpd/lib -cp ./target/FSVRPpd-1.0.jar -Xmx15g fvrpsd.test.FSVRPpdTest
The library path includes references to two folders, one for CPLEX and the other one to the folder containing the native library.
In my Java code I have:
static {System.out.println(System.getProperty("java.library.path")); System.loadLibrary("native");}
to print the java library path (as a check) and load the library. Running my code returns the following output:
/home/usr/ILOG/CPLEX_Studio1210/cplex/bin/x86-64_linux:/home/usr/FSVRPpd/lib
Exception in thread "main" java.lang.UnsatisfiedLinkError: no native in java.library.path:
[/home/usr/ILOG/CPLEX_Studio1210/cplex/bin/x86-64_linux, /home/usr/FSVRPpd/lib]
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2660)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:829)
at java.base/java.lang.System.loadLibrary(System.java:1867)
at fvrpsd.test.FSVRPpdTest.<clinit>(FSVRPpdTest.java:136)
It shows that the locations are correctly included, but it unable to find the native library, even though it is located in the second folder.
I read many posts on this on this website and tried including adding the java library path to LD_LIBRARY_PATH, but without any success.
I am looking forward to any suggestions on what I can do to identify the issue.
Your native library must be called libnative.so on Linux and native.dll on Windows.
From the documentation of System.loadLibrary:
Loads the native library specified by the libname argument.
The libname argument must not contain any platform specific prefix, file extension or path.
This aids in writing cross-platform code because the pattern is different for every platform.
You can calculate the expected file name yourself by using System.mapLibraryName, for example:
# Linux
jshell> System.mapLibraryName("native")
$1 ==> "libnative.so"
# macOS
jshell> System.mapLibraryName("native")
$1 ==> "libnative.dylib"

Use a jar java API in c# program [duplicate]

I'm an entry level programmer so please be descriptive in your responses.
I am trying to use a Java API given as a .jar file in my C# .net application. I don't know much Java, but this .jar file says "no main-class manifest attribute" when I try to run it so this means its a library? This Java API also comes with a .java file which shows how to use the library but I cannot see the code inside the .jar.
I found this question on this site, and one of the answers reads, "In simple way you can pack your java classes to jar file then In C# use Process class for execute and map IO stream." I am semi-familiar with the Process class in C# but I don't understand how I could use it to use a Java library in my C# .net project.
Is this possible? or was that answer incorrect?
If so, could you explain how I can use the .jar library in my C# app.
You can do it using IVKM.Net. IVKM.NET includes an application called ikvmc. Here’s the documentation for this tool:
http://www.ikvm.net/userguide/ikvmc.html
To use it compile your java code into a Jar.
Then run the ikvmc program:
ikvmc myCode.jar
If your jar contains a main() function, it will be converted into an exe that can be run on the CLR. Otherwise it will be converted into dll’s. To use the dll’s in your project just add them as references in Visual Studio and the same API that was available to you in Java will be accessible in your .Net application.
You can also include the IKVM.GNU.Classpath.dll dll from ikvmc and use the standard java class libraries in your application.
Have a look at IKVM ... it has tools to give you some level of interop. When you say Java API I assume you want to call some functionality from the jar rather than just execute it
You could use IKVM.NET - http://www.ikvm.net/userguide/ikvmc.html
On the official website in download - you can get
ikvmbin-7.2.4630.5 (Works up to Java 7)
However, on the owner's blog, you can download a newer version.
http://weblog.ikvm.net/default.aspx - You can get
ikvmbin-8.1.5717.0 (Works up to Java 8)
To create dll/exe use:
ikvmc hello.jar
On the other hand, if you can edit .jar lib (you created it) you
could use http://jni4net.com/ project.

Using functions from an archive file without use of .cpp

I have an archive file which contains a number of functions which are built in.
Having read the android ndk documentation I assumed that upon System.loadLibrary() in the Java class I would have access to the functions from the archive file.
I am not having access to the .cpp files so I am using only the .a + .h(header file) .
I am still new to this so some help would be appreciated.
Thank you
You have Java and you have Native (binary + .h file)
Now you need JNI (https://en.wikipedia.org/wiki/Java_Native_Interface)
JNI will helps you making call to native function (in .a file) from Java
This sample uses 2 libs: one static, the other one shared lib. It is just a framework for how to use external ( 3rd party ) libs in android platform, which might be close to what you are at. System.LoadLibrary() will load shared lib, which means you will need create your own wrapper for your static lib:
Create your java apps
Add java wrapper function (s) for your native function (s)
Generate your native function(s) prototype with javah or let android studio auto generate them for you ( right click on the java function, select generate prototype ); those functions have some special signature so they could be called by your java side code (you will see it when you get there ). Remember to add JNIEXPORT JNICALL to them (manually add them into your function if Android Studio forgets about it)
Call your lib functions inside your archive ( *.a, static lib) from your generated native function(s)
some samples could be found in the sample repo, but you will need to decide whether to use ndk-build or cmake to build your native C/C++ code. It is better to use CMake for new projects.

Java not able to load library in Eclipse project

I'm trying to load a .dll into my java/c++ project in eclipse. I've created the .dll in order for my Java project to use it with the JNI, but when I try to load the library, I get this message: "java.lang.UnsatisfiedLinkError: no hpaprogram in java.library.path". My main class is located in a different directory than the dll, but I used the flag -Djava.library.path=jni in VM Arguments. I have no idea what could be going wrong, and I've been debugging this for hours.
Here's my git repo: https://github.com/zalbhathena/Thesis-Test-Application
Also I'm using OS X if that matters.
EDIT: Here's a post I found. it states that I need a jnilib, not a dll. I've made the changes yet I still get the same error. I'm doing exactly what he is but in eclipse, so I'm not sure what's wrong.
Check if this helps:
How to set the java.library.path from Eclipse
Also, maybe we can try this another way, if not already tried.
a) Create your java class having the native methods defined.
b) Use javah to generate the required header and c files (http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javah.html).
c) Put in your code in the C file generated and use gcc to create a library of the same.

Generating Java interface from a C++ header file

We have some proprietary libraries we need to interface with. These libraries are Windows DLLs, or Linux .so files. We got the headers to define the interfaces. Since I have never done anything with native libs, I looked at JNAerator (http://code.google.com/p/jnaerator/) and the BridJ and JNA stuff.
What's a simple way to use a C++ header file and the compiled lib to generate an interface? For example, by adopting JNA in general with something like:
SomeDLL lib = (SomeDLL) Native.loadLibrary("some_dll", SomeDLL.class);
I have to keep the DLL somewhere: how do I bundle the DLL with the Jar? I use Maven to build the Jar file... but the Native.loadLibrary interface doesn't allow to directly specify a path.
JNI coding is usually a manual process of writing C++ code to create the native glue methods. There's an entire book that explains it.
In some cases, http://jna.java.net/ can automate or accelerate this process, but don't count on it.
You can't 'bundle the native libraries' unless you go down the path of using OSGi or something like the Tanukisoft packaging tool, there's no built-in feature for that purpose in Java.
You connect the dots by using -Djava.library.path to tell java where to find native libraries, or using the lower-level APIs to System.loadLibrary that allow you to specify a full path.
Watch out for interactions with PATH and LD_LIBRARY_PATH if your native libraries have dependencies in turn.
With BridJ, you can bundle the DLL/.so/.dylib just fine with the JAR, but you have to put it (or them) in a specific platform-dependent path within the JAR, which starts by "org/bridj/lib/" and ends with a platform+architecture identifier.
Here's BridJ's own source tree, which exhibits this native bundling scheme :
org/bridj/lib resource directory
If you stick to this convention, you won't have do deal with PATH, LD_LIBRARY_PATH or file extraction : BridJ.register() (called on a #Library-annotated class with native methods) will do it all for you !

Categories