To learn basic practice presence am calling string to my application. I know its too basic but am new to native languages. Like:
jstring Java_com_idiasoft_LoginActivity_NdkdealerName(JNIEnv* env, jobject javaThis)
{
return (*env)->NewStringUTF(env, "User Name");
}
Here I can call this string in particular class. But I wanna make dynamic call. like two or more classes. where am uses the same string. How can I do this?
Couldn't find a perfect solution regarding NDK but I think creating a global class in Java part could help you in this situation.
Just define that particular native function in your global class and use it anywhere.
If there is no need to instantiate the class you can also make it static and use it anywhere in your application.
Hope this helps.
Related
im currently trying to integrate a c library to my android project.
The extern function accepts a Array<Double> for example
val doubleArray= arrayOf(0.0)
MyClass().myFunction(doubleArray)
in the native part of the application, im trying to access it like this:
Java_com_mypackage_MyClass_myFunction(JNIEnv *env, jobject thiz,jdoubleArray myArray) {
jdouble *body_ = (*env)->GetDoubleArrayElements(env, myArray, 0);
}
This is the way, how the documentation tells me to access my array values. But when im doing this, i'm getting a SIGABRT.
What am i missing here? Would appreciate when you can point me the direction :)
An Array<Double> is a java.lang.Double[] in JVM terms, ie an array of objects.
You meant to create a DoubleArray, which is a double[] (the primitive).
I'm researching using libbitcoin for a project I'm going to work on, and interested in using Djinni to create the glue code for ObjC/Java for iOS and Android, respectively.
It appears there are many global functions in libbitcoin, inside a namespace, but not inside a class. I have only seen Djinni to generate a few types (classes, enums, flags, records) but I have not been able to find if a global function can be accommodated.
Is this doable? Thanks in advance.
It is not feasible since djinni produces Java bindings and there are no global functions in Java.
What you might do is to create a class with a set of static methods that will forward calls to global functions:
Bitcoin = interface +c {
static callGlobalFun1();
static callGlobalFun2(param: string);
static callGlobalFun3(): string;
}
I'm using JNI to get the music library from Android with Qt. I call upon the following Java method (which is already implemented),
public String getArtists(Context context)
...
I need to be able to get the Context of the application in order for it to work.
If it helps, when I was using Java, the following code provided the correct context.
MainActivity.this
Could anybody be of assistance in this problem?
Many thanks!
It will depend where you are making the call. Ideally you will cache the MainActivity pointer in C++.
One way to cache a pointer to use in a later JNI call is to add a native function in java such as native void onCreateNative() to you MainActivity class. In C++ you'll implement the method and cache the "thiz" pointer:
JNIEXPORT void JNICALL com_package_MainActivity_onCreateNative(JNIEnv *env, jobject thiz)
{
gCachedActivity = env->NewGlobalRef(thiz);
}
Now you can use gCachedActivity where you would have used MainActivity.this
env->CallObjectMethod(obj, s_getArtistsGetArtistsMethodID, gCachedActivity);
Of course replacing obj with the object you are calling the method on.
Lastly onCreateNative() should be called in the onCreate() method of MainActivity.
I have written a shared library which is accessed via my linux-system and via a JNI-call from java.
That library should have a global ringbuffer which must be available in the JNI-method and in the other native methods.
I thought this won't be a problem, because when I access the SL from different programs, the global variables are always as they should.
But now, in my JNI-method, the global variables seem to be not initialized (they should as the program-flow forces it).
Here is my example:
ringbuf_t ringbuffer;
void internalMethod() {
// this method is first called from system-program
ringbuffer = ringbuf_new(5000);
}
JNIEXPORT jint JNICALL Java_example_read(JNIEnv *env, jobject This) {
// this method is later called via JNI
if (!ringbuffer) {
LOGI("uhhh, why is that buffer not set?!");
}
}
What do I have to do to make the ringbuffer-variable really global so every instance/call to the shared-library access one and the same instance of that variable?
From the comments it seems you want to allocate your memory in a process and use it in another.
For this purpose it might be a good idea to look at shared memory: 'man shmget' should be a good start.
Note that this is not specifically related to JNI and is a restriction from the OS.
EDIT:
I would suggest you:
read up on shared memory - you should understand the concepts of how this works.
first try sharing memory between 2 simple applications
only then implement in your JNI application
I asked this question the other day, but wasn't too specific, so I want to re-clarify.
I am creating an Android Application which uses an existing library in C using the NDK. The problem I have run into is that the C code uses a lot of things java doesn't ( function pointers as parameters is the big problem ).
Anyway, I was wondering if I could write functions in my Java code that the C code calls. Now from what I can tell, you can do it, so I would appreciate it if no one just answered 'Yes you can, LINK." I have been looking into it but its very over my head as to what actually needs to be done.
Can anyone try to explain the process? I know it involves creating a JVM in the C code; any information that will help a newbie get on his feet will be greatly appreciated.
Thanks
EDIT :
So, I don't know what to do for these three steps.
To call a specific Java function from C, you need to do the following:
Obtain the class reference using the FindClass(,,) method.
Obtain the method IDs of the functions of the class that you want to call using the
GetStaticMethodID and GetMethodID function calls.
Call the functions using CallStaticVoidMethod, CallStaticIntMethod, and CallStaticObjectMethod.
This isn't explained too much and I have literally no experience in C. Is FindClass a C method?
Every C function that is callable from Java via JNI has a first parameter of type JNIEnv*. On the C end, this is a pointer to a pointer to a structure with a bunch of pointers to functions. Those functions are your interface to the Java world. FindClass, GetMethodID and the rest are among them.
So when you want to call FindClass from the C side, here's how you do it:
void Java_com_mypackage_MyClass_MyMethod(JNIEnv *jniEnv, jobject thiz)
{
jclass *clazz = (*(*jniEnv)->FindClass)(jniEnv, "com/mypackage/SomeClass");
jmethodID MethodID = (*(*jniEnv)->GetStaticMethodID)(jniEnv, clazz, "SomeMethod", "(I)I");
int result = (*(*jniEnv)->CallStaticIntMethod)(jniEnv, clazz, MethodID, 18);
And so forth. The line dereferences the jniEnv parameter, gets a function pointer and calls the function through it. Class and method names are completely bogus, naturally. How would I know yours.
Note: I'm talking of function pointers here, but not in the same sense as you do; those are function pointers to functions that JNI provides, not to your functions.
The verbosity of call syntax has to do with the limitations of C; in C++, you can write instead
jclass *cl = jniEnv->FindClass("com/mypackage/SomeClass");
as C++ supports function table pointers of this sort natively via virtual functions.
You can probably take some shortcuts along the way. If you're calling methods in the same class as your C point of entry, and it happens to be static, your second parameter already is a class object pointer. If you have a this pointer to the object you want to invoke a method on, you can use GetObjectClass.