在调用Android的Java方法从C ++ [英] Calling a java method from c++ in Android
问题描述
对这个问题的解决方案是在问题的底部!
你好。我想从C得到一个简单的Java方法调用++而Java调用本地方法。所以,这里是java的code:
公共类MainActivity延伸活动{
私有静态字符串LIB_NAME =名;
静态{
的System.loadLibrary(LIB_NAME);
}
/ **第一次创建活动时调用。 * /
@覆盖
公共无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.main);
TextView的电视=(TextView中)findViewById(R.id.textview);
tv.setText(this.getJniString());
}
公共无效messageMe(字符串文本){
的System.out.println(文本);
}
公共本地字符串getJniString();
}
我试图调用 messageMe 从本地code方法的过程中的 getJniString 方法调用从Java到本机。
native.cpp:
的#include< string.h中>
#包括< stdio.h中>
#包括< jni.h>
的jstring Java_the_package_MainActivity_getJniString(JNIEnv的* ENV,jobject OBJ,jint深度){
//的JavaVM *虚拟机;
// JNIEnv的* ENV;
// JavaVMInitArgs vm_args;
// vm_args.version = JNI_VERSION_1_2;
// vm_args.nOptions = 0;
// vm_args.ignoreUnrecognized = 1;
//
// //构造一个虚拟机
// jint解析度= JNI_CreateJavaVM(安培;虚拟机,(无效**)及包膜,&安培; vm_args);
//创建一个字符串
的jstring jstr = ENV-> NewStringUTF(此字符串来自JNI);
//首先要获取包含您需要调用方法的类
JCLASS clazz所= ENV->的findClass(下称/包/ MainActivity);
//获取要调用的方法
jmethodID messageMe = ENV->的GetMethodID(clazz中,messageMe,(Ljava /朗/字符串;)V);
//调用对象的方法
jobject结果= ENV-> CallObjectMethod(jstr,messageMe);
//获取C风格的字符串
为const char *海峡= ENV-> GetStringUTFChars((的jstring)结果,NULL);
的printf(%S \ N,STR);
// 清理
ENV-> ReleaseStringUTFChars(jstr,STR);
// //关闭虚拟机。
// VM-> DestroyJavaVM();
返回ENV-> NewStringUTF(你好来自JNI!);
}
在与下一个消息干净编译应用程序停止:
ERROR / AndroidRuntime(742):致命异常:主要
java.lang.NoSuchMethodError:messageMe
在* .android.t3d.MainActivity.getJniString(本机方法)
在* .android.t3d.MainActivity.onCreate(MainActivity.java:22)
显然,这意味着,方法名是错误的,但它看起来不错我。任何想法是值得欢迎的。
P.S:我不是一个C / C ++的家伙,还)
解决方案:
所以,我很搞砸了与C到C ++的转换(基本变量ENV的东西),但我得到了它的工作与下一code为C:
的#include< string.h中>
#包括< stdio.h中>
#包括< jni.h>
的jstring Java_the_package_MainActivity_getJniString(JNIEnv的* ENV,jobject OBJ){
的jstring jstr =(* ENV) - > NewStringUTF(ENV,这个来自JNI);
JCLASS clazz所=(* ENV) - >的findClass(ENV,COM / inceptix /安卓/ T3D / MainActivity);
jmethodID messageMe =(* ENV) - >的GetMethodID(ENV,clazz中,messageMe,(Ljava /朗/字符串;)Ljava /朗/字符串;);
jobject结果=(* ENV) - > CallObjectMethod(ENV,OBJ,messageMe,jstr);
为const char *海峡=(* ENV) - > GetStringUTFChars(ENV(的jstring)结果,NULL); //应该被释放,但什么赫克,这是一个教程:)
的printf(%S \ N,STR);
返回(* ENV) - > NewStringUTF(ENV,STR);
}
和下一个code的Java方法:
公共类MainActivity延伸活动{
私有静态字符串LIB_NAME =thelib;
静态{
的System.loadLibrary(LIB_NAME);
}
/ **第一次创建活动时调用。 * /
@覆盖
公共无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.main);
TextView的电视=(TextView中)findViewById(R.id.textview);
tv.setText(this.getJniString());
}
//请让我活着,即使我用这个黑暗的编程技术
公共字符串messageMe(字符串文本){
的System.out.println(文本);
返回文本;
}
公共本地字符串getJniString();
}
这是一个对象的方法,所以我认为你需要的对象传递给 CallObjectMethod
:
jobject导致= ENV-> CallObjectMethod(OBJ,messageMe,jstr);
你在做什么是相当于 jstr.messageMe()
。
修改 - 我才意识到,因为你是一个无效的方法,你应该叫:
ENV-> CallVoidMethod(OBJ,messageMe,jstr);
如果你想返回一个结果,你需要改变你的JNI的签名(即()V
表示无效$的方法C $ C>返回类型),并在Java code中的返回类型。
THE SOLUTION TO THIS PROBLEM IS IN THE BOTTOM OF THE QUESTION!
Hi. I'm trying to get a simple java method call from c++ while java calls native method. So, here's the java code:
public class MainActivity extends Activity {
private static String LIB_NAME = "name";
static {
System.loadLibrary(LIB_NAME);
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.textview);
tv.setText(this.getJniString());
}
public void messageMe(String text) {
System.out.println(text);
}
public native String getJniString();
}
I'm trying to call a messageMe method from native code in the process of getJniString method call from java to native.
native.cpp:
#include <string.h>
#include <stdio.h>
#include <jni.h>
jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj, jint depth ){
// JavaVM *vm;
// JNIEnv *env;
// JavaVMInitArgs vm_args;
// vm_args.version = JNI_VERSION_1_2;
// vm_args.nOptions = 0;
// vm_args.ignoreUnrecognized = 1;
//
// // Construct a VM
// jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
// Construct a String
jstring jstr = env->NewStringUTF("This string comes from JNI");
// First get the class that contains the method you need to call
jclass clazz = env->FindClass("the/package/MainActivity");
// Get the method that you want to call
jmethodID messageMe = env->GetMethodID(clazz, "messageMe", "(Ljava/lang/String;)V");
// Call the method on the object
jobject result = env->CallObjectMethod(jstr, messageMe);
// Get a C-style string
const char* str = env->GetStringUTFChars((jstring) result, NULL);
printf("%s\n", str);
// Clean up
env->ReleaseStringUTFChars(jstr, str);
// // Shutdown the VM.
// vm->DestroyJavaVM();
return env->NewStringUTF("Hello from JNI!");
}
After clean compilation app stops with next message:
ERROR/AndroidRuntime(742): FATAL EXCEPTION: main
java.lang.NoSuchMethodError: messageMe
at *.android.t3d.MainActivity.getJniString(Native Method)
at *.android.t3d.MainActivity.onCreate(MainActivity.java:22)
Apparently it means that method name is wrong, but it looks ok to me. Any ideas are welcome.
P.S.: I'm not a c/c++ guy, yet)
SOLUTION
So, I quite messed it up with c to c++ conversion (basically env variable stuff), but I got it working with next code for c:
#include <string.h>
#include <stdio.h>
#include <jni.h>
jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){
jstring jstr = (*env)->NewStringUTF(env, "This comes from jni.");
jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity");
jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr);
const char* str = (*env)->GetStringUTFChars(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :)
printf("%s\n", str);
return (*env)->NewStringUTF(env, str);
}
And next code for java methods:
public class MainActivity extends Activity {
private static String LIB_NAME = "thelib";
static {
System.loadLibrary(LIB_NAME);
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.textview);
tv.setText(this.getJniString());
}
// please, let me live even though I used this dark programming technique
public String messageMe(String text) {
System.out.println(text);
return text;
}
public native String getJniString();
}
It's an object method, so I think you need to pass the object to CallObjectMethod
:
jobject result = env->CallObjectMethod(obj, messageMe, jstr);
What you were doing was the equivalent of jstr.messageMe()
.
Edit - I just realized, since your is a void method, you should call:
env->CallVoidMethod(obj, messageMe, jstr);
If you want to return a result, you need to change your JNI signature (the ()V
means a method of void
return type) and also the return type in your Java code.
这篇关于在调用Android的Java方法从C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!