I have already tried NDK simple examples such as displaying data from a native code to android's java code such as this:
#include <jni.h>
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_JNIActivity_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return env->NewStringUTF("I'm C++! What the hell am I doing here in android?!");
}
}
However, I want an application wherein user will have to enter data from a textfield and have this data be pass from it's java code to the native code where calculations will be done. How will I do this?
In your Java native method, include a formal String argument that accepts the textfield value.
In C/C++, access the characters from the jstring with JNI methods like these:
jsize GetStringLength(JNIEnv *env, jstring string);
const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy);
When you're done with the characters, be sure to release them.
void ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars);
void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf);
See the documentation for these methods in the Java Native Interface Specification.
Related
I have created a cc_library in my bazel Build file and added the deps in android_binary rule
Bazel BUILD:
cc_library(
name = "native_libs",
srcs = glob([
"app/src/main/jni/**/*.cc",
"app/src/main/jni/**/*.h",
]),
)
android_binary(
name = "buildlib",
srcs = glob([
"app/src/main/java/**/*.java",
]),
manifest = "app/src/main/AndroidManifest.xml",
deps = ":native_libs",
)
And loaded the library in the specified package as
static{
System.loadLibrary("buildlib");}
And declares and calls the native function as :
Declaration:
private static native String foo(String code);
Function Call
foo("Code");
JNI FILE FUNCTION DECLARATION AND DEFINITION:
JNIEXPORT jstring JNICALL
Java_com_example_android_(foo)( JNIEnv* env, jobject thiz, jstring code );
JNIEXPORT jstring JNICALL
Java_com_example_android_(foo)( JNIEnv* env, jobject thiz, jstring code )
{
//some code
return code;
}
The library gets loaded successfully but while function call throws an error of java.lang.UnsatisfiedLinkError
How can i called the native foo() from my java file?
When I try to call JVM from thread in C++, debbuger says that JNIEnv pointer is gone. Code:
void thread_call(JNIEnv* env,jobject text_view,jmethodID setText,const char* str){
env->CallVoidMethod(text_view,setText,env->NewStringUTF(str));
}
JNIEXPORT jstring JNICALL
Java_com_example_project_1lenspath_MainActivity_initPullThread(
JNIEnv *env,
jobject, jobject text_view){
...
std::thread pull(thread_call,env,text_view,setText,std::to_string(t).c_str());
...
}
//Debugger:
error: use of undeclared identifier 'env'
Are there any ways to call JVM without JNIEnv or any other solution?
You can cache the jvm pointer inside JNI_OnLoad, e.g.
JavaVM* g_jvm;
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
g_jvm = vm;
...
return result;
}
Then use this g_jvm to do AttachCurrentThread and DetachCurrentThread, e.g.
void foo()
{
jint res = javaVM->GetEnv((void**)&env, JNI_VERSION_1_6);
if (res != JNI_OK) {
res = javaVM->AttachCurrentThread(&env, NULL);
if (JNI_OK != res) {
return NULL;
}
}
...
g_jvm->DetachCurrentThread();
}
See: https://github.com/russell-shizhen/JniExample/blob/master/app/src/main/cpp/native-lib.cpp
how can i handle more string from native-lib.cpp class
i tried this
Java:
....
public List<String> getFooAsList(){
return new ArrayList(this.getData());
}
private native String[] getData();
JNI
#include <jni.h>
JNIEXPORT jobjectArray JNICALL
como_foo_bar_getData
(JNIEnv *env, jobject jobj){
jobjectArray ret;
int i;
char *data[5]= {"Hello from C++", "Hello from B++", "Hello from A++", "Hello from D++";
ret= (jobjectArray)env->NewObjectArray(5,env->FindClass("java/lang/String"),env->NewStringUTF(""));
for(i=0;i<5;i++) env->SetObjectArrayElement(ret,i,env->NewStringUTF(data[i]));
return(ret);
}
nativ-liv.cpp
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_in_gov_civilsupplieskerala_myapplication_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
std::string hello3 = "Hello from A++";
std::string hello2 = "Hello from B++";
std::string hello1 = "Hello from D++";
return env->NewStringUTF(hello.c_str());
}
It only take first value,how can i take all string value from native-lib.cpp class
I'm working in an Android project with c++ files (NDK) but i have faced a problem
native method not found , when i add the
extern "C" {
} i got new problem which is declaration of c function '..' conflicts with .h previous declaration
here is my code
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_marwen_parojet_ocr_2_PostPhot */
#ifndef _Included_com_marwen_parojet_ocr_2_PostPhot
#define _Included_com_marwen_parojet_ocr_2_PostPhot
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_marwen_parojet_ocr_2_PostPhot
* Method: Traiter
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_marwen_parojet_1ocr_12_PostPhot_Traiter
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
this traitement_jni.h
and the .cpp file is
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv/cv.h>
#include "opencv2/ml/ml.hpp"
#include <android/log.h>
#include <jni.h>
#include "traitement_jni.h"
#include <stdlib.h>
extern "C" {
JNIEXPORT void JNICALL Java_com_marwen_parojet_1ocr_12_PostPhot_Traiter(JNIEnv* env, jobject,jstring path){
...
}
}
It seems you are passing a jclass in the declaration but a jobject in the definition. If these two types aren't aliases for the same type, this doensn't work: you cannot overload extern "C" functions.
header file:
extern "C" {
JNIEXPORT void JNICALL Java_com_marwen_parojet_1ocr_12_PostPhot_Traiter(
JNIEnv *,
jclass, // <---- here
jstring);
}
source file:
...
extern "C" {
JNIEXPORT void JNICALL Java_com_marwen_parojet_1ocr_12_PostPhot_Traiter(
JNIEnv* env,
jobject, // <---- here
jstring path){
...
}
}
android project:
i HAve c. file :
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <com_jp_algi_Corelib.h>
/* Header for class com_jp_algi_Corelib */
#ifdef __cplusplus
#define EXTCFUNC extern "C"
#elseif
#define EXTCFUNC extern
#endif
JNIEXPORT jfloatArray JNICALL Java_com_jp_algi_Corelib_vector
(JNIEnv * env, jobject clazz, jfloatArray input){
jfloatArray result;
}
jfloat* flt1 = env->GetFloatArrayElements(input,0)
;insiperd by : Eiegen android in the stackflow.
and there is some error:
C:/AA/FileBroswerActivity/jni/com_jp_algi_Corelib.c:23: error: 'env' undeclared here (not in a function)
C:/AA/FileBroswerActivity/jni/com_jp_algi_Corelib.c:23: error: 'input' undeclared here (not in a function)
/cygdrive/c/android-ndk-r5c/build/core/build-binary.mk:217: recipe for target `/cygdrive/c/AA/FileBroswerActivity/obj/local/armeabi/objs/com_jp_algi_Corelib/com_jp_algi_Corelib.o' failed
make: *** [/cygdrive/c/AA/FileBroswerActivity/obj/local/armeabi/objs/com_jp_algi_Corelib/com_jp_algi_Corelib.o] Error 1
16:52:03 Build Finished (took 672ms)
Your post is really unclear but your files should looks like this
.h file:
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
jfloatArray JNICALL Java_com_jp_algi_Corelib_vector(JNIEnv * env, jobject clazz, jfloatArray input);
#ifdef __cplusplus
}
#endif
.cpp file:
#include "yourheader.h"
#ifdef __cplusplus
extern "C" {
#endif
jfloatArray JNICALL Java_com_jp_algi_Corelib_vector(JNIEnv * env, jobject clazz, jfloatArray input)
{
jfloat* flt1 = env->GetFloatArrayElements(input,0);
}
#ifdef __cplusplus
}
#endif
Edit(after your edit):
jfloat* flt1 = env->GetFloatArrayElements(input,0);
is outside function body