I have one c++ dll file. And I know the methods used in it. I need to call these methods from my java code. I don't have access to modify the DLL file. Please provide me a solution to do this.
I created JavaCPP exactly for that purpose. I'll copy/paste some sample code and explanations from the page:
The most common use case involves accessing some legacy library written for C++, for example, inside a file named LegacyLibrary.h containing this C++ class:
#include <string>
namespace LegacyLibrary {
class LegacyClass {
public:
const std::string& get_property() { return property; }
void set_property(const std::string& property) { this->property = property; }
std::string property;
};
}
To get the job done with JavaCPP, we can easily define a Java class such as this one--although one could use the Parser to produce it from the header file as demonstrated below:
import com.googlecode.javacpp.*;
import com.googlecode.javacpp.annotation.*;
#Platform(include="LegacyLibrary.h")
#Namespace("LegacyLibrary")
public class LegacyLibrary {
public static class LegacyClass extends Pointer {
static { Loader.load(); }
public LegacyClass() { allocate(); }
private native void allocate();
// to call the getter and setter functions
public native #StdString String get_property(); public native void set_property(String property);
// to access the member variable directly
public native #StdString String property(); public native void property(String property);
}
public static void main(String[] args) {
// Pointer objects allocated in Java get deallocated once they become unreachable,
// but C++ destructors can still be called in a timely fashion with Pointer.deallocate()
LegacyClass l = new LegacyClass();
l.set_property("Hello World!");
System.out.println(l.property());
}
}
Alternately, we can produce a Java interface by parsing the header file with a config class such as this one:
#Properties(target="LegacyLibrary", value=#Platform(include="LegacyLibrary.h"))
public class LegacyLibraryConfig implements Parser.InfoMapper {
public void map(Parser.InfoMap infoMap) {
}
}
And the following build commands:
$ javac -cp javacpp.jar LegacyLibraryConfig.java
$ java -jar javacpp.jar LegacyLibraryConfig
$ javac -cp javacpp.jar LegacyLibrary.java
$ java -jar javacpp.jar LegacyLibrary
For more complex examples including Maven/IDE integration, check out the JavaCPP Presets!
Related
I want to call Linux mount command in java using JNA and populate a list of mount points from the call result but cannot understand what should be the actual return type for the interface method.
If I use int then it prints -1 without any errors. Which I think is an indication of some sort of error.
public class MountTest {
private interface CLibrary extends Library {
String[] mount();
}
public static void main(String[] args) {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
System.out.println(INSTANCE.mount());
}
}
I tried to use different return types based on the below doc but nothing works.
Default Type Mappings
I think my problem is the incorrect signature based on
My library sometimes causes a VM crash: Double check the signature of the method causing the crash to ensure all arguments are of the appropriate size and type. Be especially careful with native pointer variations. See also information on debugging structure definitions.
Could anyone help me on this. What return type should I use so that I can get access to the list of mount points.
Update:
I was able to run a Linux command by tweaking the code as below:
public class MountTest {
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int runCommand(String cmd);
}
public static void main(String[] args) {
CLibrary.INSTANCE.runCommand("mount");
}
}
Now, the problem is, Its printing to the stdout. I don't know how to read the result from stdout using JNA
By mount documentation
mount() attaches the filesystem specified by source (which is often a
pathname referring to a device, but can also be the pathname of a
directory or file, or a dummy string) to the location (a directory or
file) specified by the pathname in target.
It means that mount syscall just mount directories, it's different from the mount command. You are probably looking for getmetent, it will list all your filesystem mount points, a implementation bellow:
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
Pointer fopen(String name, String mode);
Mount.ByReference getmntent(Pointer FILE);
}
public static void main(String[] args) {
final Pointer mountFile = CLibrary.INSTANCE.fopen("/etc/mtab", "r");
if (mountFile == null) {
System.err.println("File not exists: " + mountFile);
return;
}
Mount.ByReference mpoint;
while ((mpoint = CLibrary.INSTANCE.getmntent(mountFile)) != null) {
System.out.println(mpoint);
}
}
public static class Mount extends Structure {
public String mnt_fsname;
public String mnt_dir;
public String mnt_type;
public String mnt_opts;
public int mnt_freq;
public int mnt_passno;
#Override
protected List getFieldOrder() {
List<String> fieds = new ArrayList<>();
for (final Field f : Mount.class.getDeclaredFields()) {
if (!f.isSynthetic())
fieds.add(f.getName());
}
return fieds;
}
public static class ByReference extends Mount implements Structure.ByReference {
}
}
Obs: As I know you cannot call compiled programs from JNA, just library functions and system calls, then is impossible to call mount command, if you really want to use this command then you probably want to use Runtime.getRuntime().exec or something like that.
update
Take a look at this answer there you can differentiate what is a program and what is a syscall or library function
I'm controlling some external device using my android app, and in order to control this device it provides an sdk which is a C#(.dll) files, I know how to load .dll libraries into java and how to use it, but I can't access a lot of methods inside these libraries because it takes C# native arguments like structs which is not available in Java, and I tried equivalents in Java like classes with public elements to represent a struct but it keeps give me the error: java.lang.IllegalArgumentException: Unsupported argument type
This is how I deal with the Library(using jna):
import outsource.classes.MyClass;
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Test {
public interface simpleDLL extends Library {
long H264_DVR_GetLastError(int num); // accessed without any problems
boolean H264_DVR_SetDVRMessCallBack(MyClass obj, long num); // this "MyClass" is mainly a STRUCT in the C# sdk
}
static
{
System.loadLibrary("NetSdk");
}
public static void main(String args[]) {
simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(("NetSdk"),
simpleDLL.class);
System.out.println(INSTANCE.H264_DVR_GetLastError(4));
System.out.println(INSTANCE.H264_DVR_SetDVRMessCallBack(new MyClass(),
0));
}
}
And this is how I created MyClass.Class:
public class MyClass() {
public String Id = "myDevice";
public String UserName = "admin";
public int password = 1234;
}// also tried declaring the values inside a constructor but nothing changed
and this is how the struct defined inside the sdk:
typedef struct _DEVICEINFO
{
char id[64];
char user[64];
int pw;
}DEVICEINFO,*LP_DEVICEINFO;
p.s. I know there are some ways to write an android app with C# code using VisualBasic(e.g vs-android) but that won't work in my case as the app is already written and running with java and it's pretty huge with a lot of other functionalists so it can't be rewritten.
I am developing an Eclipse RCP application and I recently started to use Groovy in it. So 99% of my code is still Java.
I read that it is possible to use Groovy to override and add methods to Java classes and I was able to test this by adding a method to the java.lang.String.
But this only works when I use the string in a Groovy class. The overridden method is not considered as being overridden in a Java class.
Here's some code:
/*
* This is a Java class
*/
public class CTabItem {
...
private API
...
public void setControl(Control control){
private API
}
}
/*
* This is also a Java class
*/
public class Control {
...
private API
...
}
/*
* This is also a Java class
*/
public class OtherClass {
...
private API
...
private void someMethodIDontKnow(){
Control control = new Control();
CTabItem tab = new CTabItem();
tab.setControl(control);
}
}
/*
* This is a Groovy class
*/
public class MyViewPart extends org.eclipse.ui.part.ViewPart {
....
public void createPartControl(Composite parent) {
/* parent (or the parent of parent) is a Control
which is set somewhere in a CTabItem to which
I don't get access */
}
}
I need to get the tab from the control. But since it's not me who instantiates MyViewPart, but some private API, I have no access to it.
Is there something Groovy could do for me here? Any suggestion or code is welcome. Thank you!
The short answer is: no, it's not possible if the code creating the object and calling the method is pure Java (i.e., non-Groovy) code. Groovy does its magic by intercepting all method calls on objects (both Java objects and Groovy objects) and using its ExpandoMetaClass to add the behavior. However, it can't change how pure Java code determines which method to call on a pure Java class. To see, run the following sample code:
// UseTheString.java (a pure Java class)
public class UseTheString {
public static void main(String[] arg) {
String s = "Hello world";
System.out.println(s);
System.out.println(s.substring(1));
ModifyStringClass.messWithMetaClasses(s);
System.out.println(s.substring(1));
}
}
and
// ModifyStringClass.groovy (a Groovy class)
class ModifyStringClass {
public static messWithMetaClasses(String t) {
java.lang.String.metaClass.substring = { int n -> "!" }
println(t.substring(1))
}
}
You'll get the output:
Hello world
ello world
!
ello world
As you can see, Groovy can override the method on a pure Java object if it is called from other Groovy code, but it can't change how the Java code uses it.
I am trying to generate a dll which I can access from java via JNA.
I just try a simple one:
CPP:
void Initialize()
{
std::cout<< "Hello World!";
}
iostream is also included and after compiling I get: CreateDll.dll
Via Visual Studio I can generate now a *.dll.
which I try loading into Java like:
public class mainRoutine {
public static void main(String[] args) {
NativeWrapper INSTANCE = (NativeWrapper) Native.loadLibrary("CreateDll" , NativeWrapper.class);
INSTANCE.Initialize();
}
static {
System.setProperty("jna.library.path", "C:\\workspace\\JNA");
}
}
There is also another Interface:
import com.sun.jna.Library;
public interface NativeWrapper extends Library {
void Initialize();
}
So but now running the Java function I get the error,
java.lang.UnsatisfiedLinkError:
Error looking up function 'Initialize':
The specified procedure could not be found.
What am I missing?
PS: I know there are many topics, but trying for a day already I have not found the solution. Please help me.
You need to both export and (if using C++) un-decorate the function name.
On windows, functions are typically made available for export with __declspec(dllexport).
On any platform, to ensure a function is exported in unmanagled form, you must use extern "C".
Specifically:
extern "C" void __declspec(dllexport) Initialize() { ... }
There are other ways to designate exported functions, but this is probably the most common and straightforward to use. If you don't use extern "C", your function will look something like InitializeZ#ASDF#, where the additional garbage characters are used by the compiler and linker to make a given function uniquely recognizable based on its calling signature.
Are you exporting the symbol:
void _declspec(dllexport) Initialize()
{
std::cout<< "Hello World!";
}
What if there is a class to be implemented ? where the .h file looks like this:
namespace simpleDLLNS
{
class simpleDLL
{
public:
char giveVoidPtrGetChar(void* param);
int giveIntGetInt(int a);
void simpleCall(void);
int giveVoidPtrGetInt(void* param);
};
}
Where should extern "C" void __declspec(dllexport) be used ?
I used it when implementing the functions. but when i opened the dll, it looked like this:
?simpleCall#simpleDLL#simpleDLLNS##QAEXXZ
I compiled following JavaScript file, "test.js", into the "test.class" :
var test = (function () {
var that = {};
that.addNumbers = function (a, b) {
return a+b;
};
return that;
}());
I would like to call the compiled JavaScript function, "test.addNumbers(1,2)", in the simple Java program "run.java" as follows :
public class run {
public static void main(String[] args) throws Exception {
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
// HOW TO CALL THE METHOD, Test.addNumbers(1,2)? Please help me!
} finally {
Context.exit();
}
}
}
I tried many ways, but failed. I read Rhino tutorial and examined many articles and examples, BUT they only show how to call JavaScript methods from the command line or the source file, "test.js".
I need to call the method from the compiled "test.class" file.
Thanks much in advance for your help!
Using javap, I believe that the JavaScript type test does not mean that the resultant Java type is this class. The generated Java type invokes the script code in its constructor; this will not result in exposing addNumbers as a Java method.
>javap -classpath . test
public class test extends org.mozilla.javascript.NativeFunction implements org.m
ozilla.javascript.Script{
public test(org.mozilla.javascript.Scriptable, org.mozilla.javascript.Contex
t, int);
public test();
public static void main(java.lang.String[]);
public final java.lang.Object exec(org.mozilla.javascript.Context, org.mozil
la.javascript.Scriptable);
public final java.lang.Object call(org.mozilla.javascript.Context, org.mozil
la.javascript.Scriptable, org.mozilla.javascript.Scriptable, java.lang.Object[])
;
public int getLanguageVersion();
public java.lang.String getFunctionName();
public int getParamCount();
public int getParamAndVarCount();
public java.lang.String getParamOrVarName(int);
public java.lang.String getEncodedSource();
public boolean getParamOrVarConst(int);
}
Reading between the lines, I'd say you need to map to Java types to do what you want. From the jsc doc:
-implements java-intf-name
Specifies that a java class
implementing the Java interface
java-intf-name should be generated
from the incoming JavaScript source
file. Each global function in the
source file is made a method of the
generated class, implementing any
methods in the interface by the same
name.
Define this interface:
//Adder.java
public interface Adder {
public int addNumbers(int a, int b);
}
Write this implementation:
//AdderImpl.js
function addNumbers(a, b) {
return a+b;
}
Compile the JavaScript with the arguments -implements Adder AdderImpl.js. Invoke the method like so:
Adder adder = new AdderImpl();
int n = adder.addNumbers(1, 2);
System.out.println(n);
I'd hazard a guess that it was probably necessary to do it this way because of differences in the languages' type systems.
I used Rhino 1.7R2. For the sake of brevity, I've avoided using packages, etc.