How can I pass Parameters to Main via JNI?
Currently I load my DLL like:
class SharedLibrary {
native void GetBuffer(ByteBuffer Buffer);;
SharedLibrary(String[] exec_args) {
String path = new File(exec_args[0]).getAbsolutePath();
System.load(path); //Load My DLL. I want to Pass this DLL some arguments.
ByteBuffer Foo = ByteBuffer.allocateDirect(.....);
GetBuffer(Foo);
}
}
How can I pass the DLL arguments? I need to pass multiple arguments.
The purpose of loading a library into Java is to fulfill Java methods which are declared with the native attribute, such as native void methodname(_arguments go here_);. You can declare one or more native methods in a class, but all of them are expected to be defined (using JNI standards) in your DLL. From Java, you call them like any other method (by using whatever arguments are defined for the method).
If there are data elements you want the DLL's initialization entry point to receive, you need to make them static members (or methods) of some class and the DLL needs to know to access that class to get them. This, however, would be quite abnormal and is probably not the best way to perform whatever it is you're looking to do.
Well, if you need "multiple parameters", any existing "dll main" won't work for you. You are most probably referring to WinAPI DllMain and you probably think that this function is mandatory to any DLL, much the same way as every C executable is expected to have main() function. It is not. JNI in particular has JNI_OnLoad which doesn't take any parameters, but so DllMain doesn't have any user-definable "multiple parameters" per your requirement. If you need your own parameters, why can't you create an initialization method? Even the DllMain doc is recommending that. DllMain is very limited in what it can do. Make the JNI init method static, so that you can call it before instantiating the SharedLibrary object in Java. What's the problem with it? Tell something about the "multiple parameters" you need so much.
Related
I'd like to start by saying please don't ask me to use the javah tool, I've had more luck writing the few jni function prototypes than getting that tool to work properly.
I know that I am loading my jni libraries properly because they work when I leave the class structure the same.
I have some package name:
package com.bb.me;
public class test {
test2 iTest = null;
public parent test()
{
iTest = new test();
return iTest;
}
//putting my native methods here work just fine
//public native void init();
//etc
}
The c jni function prototype for that above function looks like this:
JNIEXPORT void JNICALL Java_com_bb_me_test_init(JNIEnv* e, jobject i) {}
if I break that above function signature by renaming it inita and call the function I get an error like this:
No implementation found for native Lcom/bb/me/test;.init:()V
if on the other hand I move the native function to the inner class like this:
class test2 extends parent {
//public native void init();
}
and then try to call the same function, jni will complain at me a different way about unimplemented function but this time it looks like this:
No implementation found for native Lcom/bb/me/test$test2;.init:()V
I originally thought if I edited the jni function signature to something like this:
JNIEXPORT void JNICALL Java_com_bb_me_test_test2_init(JNIEnv* e, jobject i) {}
that the function would work but it doesn't seem like that's the case.
What does the "$" dollar sign mean in this jni function signature?
No implementation found for native Lcom/bb/me/test$test2;.init:()V
How can I move the location of this native function and update the jni function signatures without using the javah tool?
I'd like to start by saying please don't ask me to use the javah tool, I've had more luck writing the few jni function prototypes than getting that tool to work properly.
I won't ask you to use javah -- though it's hard not to do -- but I have to at least say that I find that remark surprising. I have found javah very easy to use indeed. If it's not working "properly" for you then I'm inclined to suspect that you have the wrong expectations.
What does the "$" dollar sign mean in this jni function signature?
The $ delimits the simple name of a nested class from the name of the class in which it is nested. This is an aspect of the JVM's internal representation of names, which is what JNI works with.
How can I move the location of this native function and update the jni function signatures without using the javah tool?
You could refer to Oracle's documentation for mapping Java native method names to C function names. The expected native function name is based on the fully-qualified JVM name of the native method's class, on the native method's unqualified name, and, if it's overloaded, on its signature. If you move a native method to a different class then you need to alter the function name to reflect the new location, and it is possible that you will also need to encode the function signature into the name if that was not already done.
The JVM name of your inner class is com/bb/me/test$test2. Supposing that the method is not overloaded, the C function name corresponding to the native method residing in that class would therefore be Java_com_bb_me_test_00024test2_init(). The arguments are a different story -- they depend on the arguments to the Java-side method as well as on whether the native method is static. I do not address them here.
I have an existing JNI method with two parameters. Been around for a while, in use, so I don't want to just change it lest the wrath of angry customers be unleashed.
But, I now need to make an adjustment.
So, I thought, make a second overloaded method with the extra parameter and deprecate the two-parameter version. That part went fine, jar builds and runs with no issues.
The problem is in the C++ side... I defined two methods, one being a wrapper for the other (two parameter calls the three parameter version), but, when I went to export the two methods, I receive:
Error 1 error C2733: second C linkage of overloaded function 'Java_com_xxx' not allowed
So, what do I do to keep the old method name and add a new method with new parameters? Is this doable?
Run javah on your Java file declaring the native methods and you will see that you need two different Java_com_xxx functions. The C-level declarations must be unique.
I'm attempting to call native methods within a 3rd party DLL, which has a C interface with methods such as:
DWORD ExampleInterfaceMethod( DWORD Mode, LPSTR Header );
I've successfully loaded the DLL using:
System.loadLibrary("DLLName");
and I've created a method:
protected native int ExampleInterfaceMethod(int type, int Nth, byte[] name);
This method doesn't seem to be using the correct variable types, as whenever I call it the following error is thrown: java.lang.UnsatisfiedLinkError: com.DLLTest.ExampleInterfaceMethod(II[B)I
What variable types do I need to use in Java in order to call this method, or am I missing something else?
With JNI, you need specially-named C functions to implement your Java native methods. You can't simply add a native method to call an existing C function - instead the normal way is creating a "wrapper" C function which calls the existing one, and is named the right way.
You might want to have a look at JNA. This is a wrapper around JNI which allows you to call C functions from the Java side without manually writing adapting native code for this.
How to declare and call a native method in c containing pointers using java?
please it is urgent.Because there is no concept of pointers in java i am getting error.
Use JNI(Java Native Interfaces) to call native methods in java. Use this JNI specification pdf as a reference "java.sun.com/docs/books/jni/download/jni.pdf".
There is even a easier approach to the subject, if you or your boss are willing to pay 50$!
Is called eXcelsior xFunction. Try the evaluation version.
Works very well and is simple to use.
The only thing xFunction library does not do have is implementation of address arithmetic in Java, which i assume you will possibly never need.
From their site:
With xFunction, you no longer need to implement those ugly native methods. Instead, you extend and instantiate xFunction classes to create conventional Java objects representing external functions, data structures, pointers, and callbacks. All necessary data conversions and external function calls are done seamlessly by the xFunction library:
import com.excelsior.xFunction.*;
...
/* Call Beep() from KERNEL32.DLL */
xFunction f =
new xFunction( "kernel32",
"int Beep(int,int)" );
f.invoke( new Argument(1770),
new Argument(100) );
So, I need to dynamically create (or inject) methods into an object that have a specific return type and method signature, because a Java tool we're using will be finding this methods via Reflection and checks for void type. Method names will be determined at runtime.
Using metaClass. = { ... } however adds a closure which doesn't show up as a regular method (even if it can be used as one) and also has a return type.
I can't modify the method finding code, and it it not Groovy-aware.
I can't use methodMissing() or invokeMethod() because the method needs to actually exist. If I could overload class.getMethods() I think it would be possible, but I can't figure out how.
Is there any way to do this in Groovy?
You could use AST Transformations to add the code at compile time, but it wont work on classes that you don't compile, so I'm guessing that probably wont work.
You could probably replace the object with a CGLIB based proxy. If you can be more specific about the code in question...
EDIT: A little more info. Groovy metaClass magic is not available in Java unless the Java code were to explicitly call groovyClass.invokeMethod("someMethod",args);. So there isn't a way to do what you're asking with MetaClasses. CGLIB maybe.