I need to add a bool to an object map, my bool is defined as a primitive, and I need to convert it to an object.
How do I do that ?
You can convert your bool to a jboolean then box the jboolean into a Boolean jobject with JNI calls like this:
jboolean value = true;
jclass booleanClass = env->FindClass("java/lang/Boolean");
jmethodID methodID = env->GetMethodID(booleanClass, "<init>", "(Z)V", false);
jobject booleanObject = env->NewObject(booleanClass, methodID, value);
Related
im trying to get the value of an int which is non static
java code
public int valuex = 500;
public native int intfromjni();
native code
JNIEXPORT jint JNICALL Java_com_samplejni_cls_intfromjni(JNIEnv* env, jobject thiz)
{
jclass x = env->GetObjectClass(thiz);
jfieldID f = env->GetFieldID(x, "valuex", "I");
int i = env->GetIntField(x, f);
return i;
}
but it throws crash with log
JNI DETECTED ERROR IN APPLICATION: jfieldID int com.samplejni.cls.valuex not valid for an object of class java.lang.Class<com.samplejni.cls>
here
int i = env->GetIntField(x, f);
you trying to use jclass to get a particular object's value. It would work for static fields.
For non-static firelds you should use jobject:
int i = env->GetIntField(thiz, f);
I am trying to use a "QMap", in the class prototype:
QMap<QString, TargetsInfo*> m_targets;
In an access method I have:
TargetsInfo* TargetsModel::addTarget(int division, int camera, int map) const {
TargetsInfo* target = getTarget(division, camera, map);
if (target == nullptr) {
const QString key = makeKey(division, camera, map);
target = new TargetsInfo();
if ( target != nullptr ) {
m_targets.insert(key, target);
}
}
return target;
}
TargetsInfo* TargetsModel::getTarget(int division, int camera, int map) const {
const QString key = makeKey(division, camera, map);
QMap<QString, TargetsInfo*>::iterator itr = m_targets.find(key);
return (its == m_targets.end()) ? nullptr : itr.value();
}
When I compile I get the following errors which I am struggling to see what is wrong:
C2663: 'QMap<QString, TargetInfo *>::insert': 2 overloads have no legal conversion for 'this' pointer
C2440: 'initialising': cannot convert from 'QMap<QString, TargetInfo *>::const_iterator' to 'QMap::<QString, TargetInfo *>::iterator'
No constructor could take the source type, or constructor overload resolution was ambiguous
For the second error change
QMap<QString, TargetsInfo*>::iterator itr = ...
to
QMap<QString, TargetsInfo*>::const_iterator itr = ...
Your getTarget method is const so m_targets.find returns a const iterator (otherwise you could change m_targets inside your supposedly const method).
For the first error, remove const from your addTarget method. Obviously a method which adds items to m_targets should not be const.
I have following code which accepts int value at JAVA level
dataObj.property(20);
This is the definition of property function
void property(Object value){
// JNI called
}
JNI function definition
Java_com_XXX_XXXX_JNIProperty(JNIEnv *a_pEnv, jclass, **jobject a_oPropertyValue**) {
// how to convert jobject to Integer object and then get the intValue
jclass cls = a_pEnv->FindClass("java/lang/Integer");
jmethodID getVal = a_pEnv->GetMethodID(cls, "intValue", "()I");
int i = a_pEnv->CallIntMethod(value, getVal);
}
How to convert jobject which was of type Object in Java to Integer object in JNI and parse int value ?
For a class in Java
public class PassObject {
public static native void displayInt(Object obj);
public static void property(int value) {
PassObject.displayInt(value);
}
public static void main(String[] args) {
PassObject.property(44);
// make sure to be careful in your case,
// as you make assumption that "Object" will be of type "Int"
// It's really easy to be very nasty.
PassObject.displayInt("44");
}
}
you can use following JNI code
JNIEXPORT void JNICALL Java_recipeNo055_PassObject_displayInt
(JNIEnv * env, jclass obj, jobject objarg) {
jclass cls = (*env)->GetObjectClass (env, objarg);
jmethodID integerToInt = (*env)->GetMethodID(env, cls, "intValue", "()I");
jint result = (*env)->CallIntMethod(env, objarg, integerToInt);
printf("Passed value: %d\n", result);
}
if you want to be extra careful, you can always do
jclass cls = (*env)->GetObjectClass (env, objarg);
if( (*env)->IsInstanceOf(env, objarg, (*env)->FindClass(env, "java/lang/Integer")) ) {
jmethodID intValue = (*env)->GetMethodID(env, cls, "intValue", "()I");
jint result = (*env)->CallIntMethod(env, objarg, intValue);
printf("%-22s: %d\n", "Passed value (int)", result);
} else {
// error
}
JNIEXPORT jstring JNICALL Java_com_xxx_xpdf_PdfToText_getTextOnly(JNIEnv *env, jclass obj,
jstring pdf_path) {
const char *pdf = env->GetStringUTFChars(pdf_path, 0);
std::string content;
unsigned int i = getTextFromPDF(pdf, &content);
env->ReleaseStringUTFChars(pdf_path, pdf);
const char *result = content.c_str();
jstring str = env->NewStringUTF(result);
return str;
}
Do I need to relase str and content here ? And why ?
No. str refers to a Java object which continues to exist beyond this JNI method, as it is the return value. content is a C++ local object which is auto-destroyed when its declaring scope exits.
What is recommended template set or library to acquire/release JNI resources from C++ code?
"Bad" example:
//C++ code
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobject obj, jstring javaString)
{
//Get the native string from javaString
const char *nativeString = env->GetStringUTFChars(javaString, 0);
//Do something with the nativeString
//DON'T FORGET THIS LINE!!!
env->ReleaseStringUTFChars(javaString, nativeString);
}
Obviously, everybody uses a template set, not the code above.
For jstring it calls GetStringUTFChars to acquire resource and ReleaseStringUTFChars to release, when object goes "out of scope".
Gotta be something similar to auto_ptr template, but tailored to JNI to call GetStringUTFChars/ReleaseStringUTFChars for jstring, for example.
You can use std::unique_ptr in C++11, which allows you to set the deleter yourself:
#include <memory>
#include <functional>
typedef std::unique_ptr<char const[], std::function<void(char const*)>> jni_string_ptr;
// the "std::function" is needed to store any callable†
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobject obj, jstring javaString)
{
//Get the native string from javaString
jni_string_ptr nativeString(env->GetStringUTFChars(javaString, 0),
[=](char const* p) mutable{ env->ReleaseStringUTFChars(javaString, p); });
// lambda as the deleter
// mutable needed if "ReleaseStringUTFChars" is a non-const method
//Do something with the nativeString
// nativeString automatically calls the passed deleter
}
If you're stuck in C++03 and don't have access to std::unique_ptr, boost::shared_array provides a.. viable alternative.
#include <boost/shared_ptr.hpp>
typedef boost::shared_array<char const*> jni_string_ptr;
struct jni_string_deleter{
jni_string_deleter(JNIEnv* e, jstring js)
: _env(e), _java_string(js) {}
void operator()(char const* p) const{
_env->ReleaseStringUTFChars(_java_string, p);
}
private:
JNIEnv* _env;
jstring _java_string;
};
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobject obj, jstring javaString)
{
//Get the native string from javaString
jni_string_ptr nativeString(env->GetStringUTFChars(javaString, 0),
jni_string_deleter(env, javaString));
//Do something with the nativeString
// nativeString automatically calls the passed deleter
}
† You can also use a specific delter type here, as with the shared_array example, to avoid the type-erasure overhead of std::function:
struct jni_string_deleter{
jni_string_deleter(JNIEnv* e, jstring js)
: _env(e), _java_string(js) {}
void operator()(char const* p) const{
_env->ReleaseStringUTFChars(_java_string, p);
}
private:
JNIEnv* _env;
jstring _java_string;
};
typedef std::unique_ptr<char const[], jni_string_deleter> jni_string_ptr;
// create
jni_string_ptr(env->get_the_chars(), jni_string_deleter(env, javaString));
The keyword here is RAII:
class jni_string {
public:
jni_string(JNIEnv *env, jstring javaString)
: env_(env), javaString_(javaString)
{ nativeString_ = env_->GetStringUTFChars(javaString_, 0); }
~jni_string() { env_->ReleaseStringUTFChars(javaString_, nativeString_); }
operator const char *() const { return nativeString_; }
private:
jni_string(const jni_string &x);
jni_string &operator=(const jni_string &x);
JNIEnv *env_;
jstring javaString_;
const char *nativeString_;
};
Usage would be:
//C++ code
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobject obj, jstring javaString)
{
//Get the native string from javaString
jni_string nativeString(env, javaString);
//Do something with the nativeString
}