I am calling initPath method and get a crash, only in Samsung galaxy tab with API 16. Can any one please tell me what am I doing wrong. The method is-
JNIEXPORT void JNICALL Java_com_example_prat_render_GLLib_initPath (JNIEnv *env,jobject obj, jstring name) {
const char *str= (*env).GetStringUTFChars(name,0);
FilePath::folderPath = std::string(str); //Crashes at this line
FilePath::folderPath.c_str());
(*env).ReleaseStringUTFChars( name, str);
}
First, could you run it without FilePath::folderPath ? This way we can check if the problem is in JNI conversion, or when assigning to "folderPath".
Could you also log the content of "str" with __android_log_write(ANDROID_LOG_ERROR, "Tag", "Error msg");
Next steps would be dependent on the outcome of above check.
Related
I'm trying to call a JNI function from my Java code in an android app,
The function is called but the parameters value in the JNI function is not the same as the one passed in the function.
here are my java declaration and call:
public native void setIA(Integer model);
setIA(1);
and here is my JNI function
extern "C" JNIEXPORT void JNICALL
Java_com_sfy_vitaltechnics_Utils_Parameters_setIA(JNIEnv *env, jobject thiz, jint model) {
LOGD( "This is a number from JNI: %d", model );
}
I get value like -578062932 but it's never the same value.
I tried several cast and type of arguement(long, double, float, string and thir java equivalent).
and everytime it give me weird value(for string it give me non UTF-8 character)
I think the problem come from my way of declaring the function but I'm not sure
Integer corresponds to jobject in C, so you should either alter C function or change java declaration to setIA(int model); to match existing C function.
I have Android app, where I need to use C++ code. But I realised, I have problem to call C++ function. I have read something about it and tried to write something, I thought it could work. Here is my code:
private native int test(int a);
private void process() {
int ret=test(5);
Toast.makeText(this, String.valueOf(ret), Toast.LENGTH_LONG).show();
}
And my C++ code is:
#include <jni.h>
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_woodem_woodem_1opencvgrains_Main_test(JNIEnv *env, jint a)
{
return a*a;
}
Of course, my real function is much more complicated and I need to pass about 6 arguments, but I hope, this can illustrate.
NOTE: Even this code doesn't work to me.
My application crash immediately after calling process(). Could you please advice me, what am I doing wrong? Compiler tells me nothing and I have no idea, where the problem is.
You are forgetting about the second argument. For example method void test() will have JNI signature JNIEXPORT void JNICALL Java..._test(JNIEnv *env, jobject thiz). In your case, edit signature to (JNIEnv *env. jobject thiz, jint a).
Edit
The previous version showed a signature for a static function. I've updated it to match instance function.
For static signature is (JNIEnv *env, jclass clazz).
You've declared your native function as private native int test(); passing an integer argument to it.
It should be private native int test(int num);
When I call a native code for first time it returns proper result, but the second time it returns garbage value.
Here's the native code :
JNIEXPORT jstring JNICALL
Java_com_example_project_NativeCodes_method2(JNIEnv *env, jobject thisObj,
jstring st) {
const char* st1=env->GetStringUTFChars(st,0);
string str=st1;
const int len=str.length();
for(int i=0;i<len;i++){
if (str[i]>=97 && str[i]<=122)
str[i] = str[i]-32;
}
.....
env->ReleaseStringUTFChars(st, st1);
return env->NewStringUTF(str.c_str());
}
And in Java class I declare native method as follows
public class NativeCodes(){
static{
System.loadLibrary("abclib");
}
public synchronized native String method2(String s);
}
In MainActivity.java I call native method like:
String s1,s2,s3,s4;
s1=edttxt1.getText().toString();
s2=edttxt2.getText().toString();
NativeCodes nc=new NativeCodes();
s3=nc.method2(s1);
s4=nc.method2(s2);
While debugging I find s3 gets the proper result whereas s4 receives garbage value.
I think I'm releasing the pointer properly with env->ReleaseStringUTFChars(st, st1);
But if a Log() statement is inserted between two calls for the method, both calls return correct result. For example,
s3=nc.method2(s1);
Log.i("String","Value: "+s3);
s4=nc.method2(s2);
Log.i("String","Value: "+s4);
This gives expected result. But I don't want to insert unnecessary code as there are many such native method calls made.
where am I doing wrong? Any help is highly appreciated.
This is driving me crazy! I'm making a library with ndk, the linking was fine but I find that, when calling a method, the value of the argument passed to the corresponding c function is incorrect.
My java class is as follows
package ccme.usernet.love;
class LovePlayerEngine {
static {
System.loadLibrary("loveplayer");
}
public static native void init(int id);
}
And my C file is as follows:
#include <jni.h>
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "TEST", __VA_ARGS__))
JNIEXPORT void JNICALL Java_ccme_usernet_love_LovePlayerEngine_init(JNIEnv *env, jint id)
{
LOGI("INIT with id %d\n", id);
}
The compiling and library linking was fine and the app was running.
But when I called LovePlayerEngine.init(0); somewhere in my java code, I get some bad values such as 1079062016 which is not stable and will change on different runs.
My other tests such as passing variables instead of constants or passing a String all failed in getting unexpected values.
Anyone has got any clue of where the problem could be? This is sickin me, I've never encountered this in my former ndk projects.
You're missing a parameter in your call. It should be JNIEXPORT void JNICALL Java_ccme_usernet_love_LovePlayerEngine_init(JNIEnv *env, jobject obj, jint id)
The missing parameter means you're using the object as the int value by mistake.
Gabe Sechan's answer will get you up and running for now, but the second parameter for static methods is jclass, not jobject.
Java_ccme_usernet_love_LovePlayerEngine_init(JNIEnv *env, jclass cls, jint id)
I try to get a android app running, which implements part of it's code in native.
It does find the shared library, but when it attempts to run it in the Emulator and it calls loadNativeCode I get:
AndroidRuntime(1342): java.lang.UnsatisfiedLinkError: loadNativeCode
As far as I traced the code it seems to miss a call to register_android_app_NativeActivity which sets up the loadNativeCode mapping. But since this is done in the runtime I have no clue why it does not work.
JNI
loadNativeCode native function MUST format as:
Static way:
JNIEXPORT void JNICALL Java_com_tapir_android_jniutils_test_MainActivity_emptyf(JNIEnv *env, jobject obj)
{
...
}
package name is com.tapir.android.jniutils.test
class name is MainActivity
function name is emptyf
Dynamic way,use RegisterNatives to register your native function in JNI_onLoad function
JNINativeMethod nm;
nm.name = "emptyf";
/* method descriptor assigned to signature field */
nm.signature = "()V";
nm.fnPtr = native_emptyf;
env->RegisterNatives( cls, &nm, 1);
native_emptyf MUST like as
void native_emptyf(JNIEnv *env, jobject obj)
{
...
}
hope can help u