Let's take the following code
public class SomeClass {
public OtherClass method(final String param1,final String param2){
AnotherClass obj1 = AnotherClass.getInstance();
return obj.instanceMethod(new YetAnotherClass<OtherClass>() {
#Override
public OtherClass run() {
return OtherClass.get(param1, param2);
}
});
}
}
My question is there any way that I can implement the interface in C/C++ through JNI, without creating a native method in Java?
One option is the Java Native Access (JNA) library. Have a look at its project page at JNA. I quote from its project site:
JNA provides Java programs easy access to native shared libraries without writing anything but Java code - no JNI or native code is required. This functionality is comparable to Windows' Platform/Invoke and Python's ctypes.
The following example from the project's toturial page demonstrates how it is used to call the printf function from the native library that the function is defined in:
package com.sun.jna.examples;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {
// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
On Windows, the printf function is defined in the msvcrt.dll and the sample loads that DLL and calls the function from it.
The JNA project is mature and according to its web page, it has some very famous users.
It should be pointed out that JNA itself uses the JNI under the hood but in most cases, you do not need to use JNI yourself. Therefore, you can focus on implementing your native code in C (create your own DLL or Shared Library files) and then load them in Java with JNA.
Related
I have a 3rd party Win32 dll, written in C++, which I need to load in my eclipse java project and call some methods from it. What is problematic - all the classes which I really need from this dll have virtual functions. I've created a dummy C++ project, which received all the stuff via static linking and via my self-defined C++ class. Everything is working in my C++ world. Now I want to load my dummy dll (which in turn loads all other stuff I need) in my java project. The code in cpp world looks like this (I've mixed up .h and .cpp for simplicity):
class Dummy : public VirtualClassFromLib
{
public:
//...
//some standard stuff here
//...
void method1()
{
VirtualClassFromLib::function1();
}
void method2()
{
//a header is loaded with #include
AdditionalStructureFromHeader object;
VirtualClassFromLib::function2(object);
}
void virtual_function()
{
std::cout << "Cool, now you are not virtual";
}
//...
}
where function1 and function2 are not virtual in the base class and virtual_function is.
I'm a newbie in JNI and as far as I understood, I should write a "mirror" class with the same method's and other stuff's names in my java project. Question: how to deal with this VirtualClassFromLib? Like, this VirtualClassFromLib has a very complicated structure with a wide usage of self-defined structures in the original dll. Or don't I need to "mirror" that completely to java project? I don't get it from examples and tutorials in the Internet.
I'm having trouble trying to call a function writed in C# from Java. I have already loaded the dll that contains the function.
Error message:
java.lang.UnsatisfiedLinkError: app.clsValidation.validate(Ljava/lang/String;)Ljava/lang/String;
C# code compiled into a 64-bit dll:
namespace library {
public class clsValidation {
public string validate(string txt) {
return txt;
}
}
}
Java code
The class:
package app;
public class clsValidation {
static {
System.loadLibrary("library");
}
public native String validate(String txt);
}
How I'm calling it in Java:
String txt = "something";
String result = new clsValidation().validate(txt);
That's to be expected. Your Java code treats the C# DLL as if it were an unmanaged library. It is not. It does not export unmanaged functions that can be imported using LoadLibrary and GetProcAddress.
If you wish to export unmanaged functions from your .net DLL then you can:
Use Robert Giesecke's UnamanagedExports to do so.
Make a mixed mode C++/CLI assembly which exports unmanaged functions.
Other options would include exposing the functionality through COM which is readily consume from Java.
I made a dll in C++ and wrote this class in java:
public class VolumeControl {
public native float GetVolume();
public native void SetVolume(float val);
public native void VolumeUp();
public native void VolumeDown();
public native void Mute();
static {
System.load("some_path/VolumeControl.dll");
}
}
it works good, if I call functions from this file, but when I'm trying to do this:
public class Server {
public static void main(String[] args) {
VolumeControl ctrl = new VolumeControl();
ctrl.Mute();
}
}
I get this:
Exception in thread "main" java.lang.UnsatisfiedLinkError:
RemoteControl.VolumeControl.Mute()V
Both classes are in the same package, of course. How can I solve it? Thanks.
Update1: OK the problem was, that I added these classes to package. When I move them to default package, everything works good. But now if I want to use this dll with different packages, I need to rebuild it.
Update2: Actually I can't add it to package at all, when I'm trying: #javah VolumeControl, I get Error:
Could not find class file for 'VolumeControl'.
Update3: I added manually name of package to C++ functions and it works. Thanks.
The use of javah utility may help if integrated into a makefile to ensure the interface is always assumed on both side (client/server).
i have a dll driver to use in my Java application.
I read that i need to create a dll bridge for JNI. First of all I would like to know if exists some utility to creare automatically this bridge.
I have the source code of the Dll, and I also know how to creare my bridge header file (javah) but I can not understand how to put into bridge implementation because i just need to call the driver method....
Can you help me?
For example this is the header of my driver:
BOOL CALLINGCONV IsInitialized();
int CALLINGCONV Initialize(int Slot);
int CALLINGCONV Finalize();
int CALLINGCONV FinalizeML(int nSlot);
I also read about JNA, it seems easier but maybe it not very fast, is it true?
Thnak you
JavaCPP is as easy as JNA, but as fast as raw JNI. For example, this Java class could let access efficiently those four functions in Java, assuming the header and library files are named "Driver.h" and "Driver.lib" respectively:
import com.googlecode.javacpp.*;
import com.googlecode.javacpp.annotation.*;
#Platform(include="Driver.h",link="Driver")
public class Driver {
static { Loader.load(); }
public static native #Cast("BOOL") boolean IsInitialized();
public static native int Initialize(int Slot);
public static native int Finalize();
public static native int FinalizeML(int nSlot);
}
I can suggest you 2 different libraries that make easier work with JNI
SWIG
JACE
I created a Java code that tries to access the method LoadProject of the class IProjectFactory defined in myAPI.dll. The description of the DLL file says: IProjectFactory is used to load a project file into memory. IProjectFactory is a static class in the myAPI.dll assembly. It exposes the LoadProject method that takes a string containing the path to the file to load, and returns a reference to the resulting IProject. Using the IProject interface you can then manipulate the loaded project in various ways.
import com.sun.jna.Library;
import com.sun.jna.Native;
public class MyClass {
public interface IProjectFactory extends Library {
public Object LoadProject(String fileName);
}
public MyClass() {
//System.loadLibrary("myAPI");
load();
}
void load() {
String fileName = "xxx.sp";
IProjectFactory api = (IProjectFactory) Native.loadLibrary("myAPI",IProjectFactory.class);
try {
Object project = api.LoadProject(fileName);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
After running this code, the following error message has been generated:
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: Error looking up function 'LoadProject': The specified procedure could not be found.
at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:350)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:330)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at $Proxy0.LoadProject(Unknown Source)
Does it mean that myAPI does not contain the class IProjectFactory with the method LoadProject?
You can call functions in native libraries with JNI or JNA. Primitive types are mapped. Certain structures are possible also. Even callback functions are possible. See JNA's mapping table.
What is impossible, by design: Getting a class or interface that was designed for a different runtime environment (like CLR) and use it seamless within the JVM.
So if you have a native procedural/functional library that just returns pointers or primitive types then you can use it quite well.
If you need to work with objects that are returned then you are out of luck. You need to run them in their native environment and find some way of interprocess communication.