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
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?
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 am doing development in Android using C/C++. I have a C++ function, that needs to be called from a C file. Here is what I am doing right now, but I get the error
undefined reference to __check_expiry
The C++ function is defined in "a.h" and implemented in "a.cpp". I am including "a.h" in"b.c" file and calling the method "__check_expiry" from "b.c" file.
a.h :
#ifdef __cplusplus
extern "C" {
#endif
static int __check_expiry(void);
#ifdef __cplusplus
}
#endif
a.cpp:
extern "C" {
static int __check_expiry() {
vz::lock_guard<std::mutex> guard(mutex_check, lock_hooker_check);
JNIEnv *env = NULL;
static bool __is_attached_1 = false;
if ((env = __getEnv(&__is_attached_1)) == NULL) {
//log_info("getEnv fail\r\n");
}
assert(!__is_attached_1);
int obj = env->CallStaticIntMethod((jclass) g_class, g_methodID);
log_info("Returned value from JAVA %d", obj);
__releaseEnv(__is_attached_1);
guard.~lock_guard();
return obj;
}
}
b.c:
#ifdef __cplusplus
extern "C" {
#endif
#include "a.h"
#ifdef __cplusplus
}
#endif
static int tunnel_to()
{
int value = __check_expiry();
}
Static functions are not exported. Remove the static qualifier.
(Unrelated: as long as you #include "a.h" from a.cpp, you don't need the extern "C" in your source file.)
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.
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