当前位置: 首页 > news >正文

装饰公司网站建设流程怎么做一元抽奖网站

装饰公司网站建设流程,怎么做一元抽奖网站,点网站出图片怎么做,衡水网站设计公司哪家好Android JNI复杂用法#xff0c;回调#xff0c;C中调用Java方法 一、前言 Android JNI的 普通用法估计很多人都会#xff0c;但是C中调用Java方法很多人不熟悉#xff0c;并且网上很多介绍都是片段的。 虽然C/C调用Java不常用#xff0c;但是掌握多一点还是有好处的。…Android JNI复杂用法回调C中调用Java方法 一、前言 Android JNI的 普通用法估计很多人都会但是C中调用Java方法很多人不熟悉并且网上很多介绍都是片段的。 虽然C/C调用Java不常用但是掌握多一点还是有好处的。 Android JNI的基础知识介绍之前已经有介绍不熟悉的可以先看看 Android Jni的介绍和简单Demo实现 https://blog.csdn.net/wenzhi20102321/article/details/136291126 本文主要介绍JNI C调用Java代码实现和相关知识有兴趣的可以看看。 二、C调用Java方法实现代码 1、上层代码 MainAcitvity.java package com.demo.jnicallback;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.util.Log; import android.widget.TextView;public class MainActivity extends AppCompatActivity {String TAG MainActivity.java;static {System.loadLibrary(native-lib);}Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.i(TAG, conCreate);TextView tv findViewById(R.id.sample_text);String jniString stringFromJNI();Log.i(TAG, conCreate cppCallBackMethod jniString jniString);tv.setText( jniString);}//C调用Java 的方法定义成private方法cpp也是可以调用到的因为是通过反射过来的public void cppCallBackMethod(String name, int age) {Log.i(TAG, cppCallBackMethod name name ,age age);}//Java 调用到 cpp 的native方法public native String stringFromJNI();}布局上未做修改运行后的默认字符串Hello from C。 Java代码这里加了一个给C调用过来的方法具体实现效果可以看是日志。 2、cpp代码 native-lib.cpp 代码 #include jni.h #include string#include android/log.h //添加头文件 #define LOG_TAG native-lib.cpp //定义TAG #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)#include iostream #include chrono #include threadextern C JNIEXPORT jstring JNICALL Java_com_demo_jnicallback_MainActivity_stringFromJNI(JNIEnv* env,jobject thiz /* this */) {std::string hello Hello from C;LOGI(stringFromJNI hello %s, hello.c_str());//c调用Java方法public void cppCallBackMethod(String name, int age)jobject m_object env-NewGlobalRef(thiz);//创建对象的本地变量jclass mainActivityClsenv-FindClass(com/demo/jnicallback/MainActivity);//获取类对象jmethodID cppCallBackMethod env-GetMethodID(mainActivityCls, cppCallBackMethod, (Ljava/lang/String;I)V);const char *message cppA;int age 10;env-CallVoidMethod(m_object, cppCallBackMethod, env-NewStringUTF(message), age);while (age 50) {//睡眠1秒std::chrono::seconds duration(1); // 休眠一秒钟std::this_thread::sleep_for(duration);age age 10;env-CallVoidMethod(m_object, cppCallBackMethod, env-NewStringUTF(message), age);}return env-NewStringUTF(hello.c_str()); } 上面代码可以看到获取类对象是为了获取方法id获取对象的本地变量是为了调用方法。 网上有些示例可能写法不一样熟悉c代码的应该知道env-“的写法和”(*env).是一个意思。 3、效果日志 //Java打印最开始日志 2024-03-01 16:27:50.401 I/MainActivity.java: conCreate //cpp文件打印开始的日志 2024-03-01 16:27:50.402 I/native-lib.cpp: stringFromJNI hello Hello from C //cpp调用Java部分日志在Java代码每隔一秒的打印 2024-03-01 16:27:50.402 I/MainActivity.java: cppCallBackMethod name cppA,age 10 2024-03-01 16:27:51.403 I/MainActivity.java: cppCallBackMethod name cppA,age 20 2024-03-01 16:27:52.403 I/MainActivity.java: cppCallBackMethod name cppA,age 30 2024-03-01 16:27:53.403 I/MainActivity.java: cppCallBackMethod name cppA,age 40 2024-03-01 16:27:54.404 I/MainActivity.java: cppCallBackMethod name cppA,age 50 //Java onCreate最后的日志打印C返回的字符串 2024-03-01 16:27:54.404 I/MainActivity.java: conCreate cppCallBackMethod jniString Hello from C上面的代码就有Java -- C和C -- Java的代码流程。 注意这里的示例代码添加了睡眠代码如果在主线程长时间执行任务是有可能导致ANR的。 4、cpp代码 native-lib.cpp 代码另一种写法 下面这种写法不用NewGlobalRef创建对象的本地变量。 中间的区别就是这里函数的调用没有使用-“,使用的”(*env). extern C JNIEXPORT jstring JNICALL Java_com_demo_jnicallback_MainActivity_stringFromJNI(JNIEnv* env,jobject thiz /* this */) {std::string hello Hello from C;LOGI(stringFromJNI hello %s, hello.c_str());//c调用Java方法public void cppCallBackMethod(String name, int age)jclass mainActivityCls(*env).FindClass(com/demo/jnicallback/MainActivity);//获取类对象jmethodID cppCallBackMethod (*env).GetMethodID(mainActivityCls, cppCallBackMethod, (Ljava/lang/String;I)V);const char *message cppA;int age 10;(*env).CallVoidMethod(thiz, cppCallBackMethod, env-NewStringUTF(message), age);while (age 50) {//睡眠1秒std::chrono::seconds duration(1); // 休眠一秒钟std::this_thread::sleep_for(duration);age age 10;(*env).CallVoidMethod(thiz, cppCallBackMethod, env-NewStringUTF(message), age);}return env-NewStringUTF(hello.c_str()); } 上面的代码运行也是一样的效果。 -“和”(*env).有啥区别因为不是很熟悉还还说不清。 上面不同写法调用方法的参数是有区别的其实就是函数api的参数要求不同具体可以看到jni.h的源码。 三、其他 1、C到Java 相关api函数介绍 上面示例中使用用到的api 1jobject m_object env-NewGlobalRef(thiz);//创建对象的本地变量 2jclass mainActivityClsenv-FindClass(com/demo/jnicallback/MainActivity);//获取类对象3jmethodID cppCallBackMethod env-GetMethodID(mainActivityCls, cppCallBackMethod, (Ljava/lang/String;I)V);4env-CallVoidMethod(m_object, cppCallBackMethod, env-NewStringUTF(message), age);上面1和2是没什么研究价值的NewGlobalRef和FindClass都是固定的写法。 3和4的不用方法的调用区别就比较大了使用不同的api函数还可以修改Java的变量属性。 静态方法和动态方法调用的api函数也不一样有返回值的方法和没有返回值的方法调用的api函数也是不一样的。 并且Java方法或者变量即使是private修饰的也不影响cpp调用过去因为反射是不受修饰符影响的。 第3步里面的签名字符串“(Ljava/lang/String;I)V”,表示的是Java的方法和返回值的签名唯一性 这里面的签名字符串都是根据Java方法和方法的参数进行变化的。 下面对3、4步的代码相关知识做展开介绍。 2、调用获取不同方法和变量的api 方法、变量修饰类型表格 函数描述描述GetFieldID得到一个实例的域的IDGetStaticFieldID得到一个静态的域的IDGetMethodID得到一个实例的方法的IDGetStaticMethodID得到一个静态方法的ID 上面Jni.cpp调用Java代码已经用到部分api方法并且从字面含义也是比较容易里面这个表格的api的具体作用。 这个表格的用于就是为了获取到方法的修饰类型比如方法静态方法变量静态变量。 毕竟不同的修饰类型在编译过程是有差异的。所以要区分。 3、Java签名类型字符串 常用的数据类型及对应字符: 上面示例中的(Ljava/lang/String;I)V);字符串都是根据Java的方法通过下面这个表格转换来的。 Java 类型Jni中表示的符号备注booleanZ不是类型首字母大写byteBcharCshortSintIlongLfloatFdoubleDvoidVobjects对象Lfully-qualified-class-name;L全类名;记得最后是有分号的Arrays数组[array-type [数组类型methods方法(argument-types)return-type(参数类型)返回类型 这个表格是有有啥用就更多人懵逼了。 其实这些类型符号表示的是Java方法或者属性的一个签名唯一性目前就是为了让Jni.cpp调用到Java代码。 举个例子就很容易清楚了 //XXX.Javaint age;String name;public int add(int number1,int number2){System.out.println(c/C居然调用了我);return number1number2;}//jni.cpp 修改Java属性值和调用Java方法示例//获取类对象 jclass mainActivityClsenv-FindClass(com/zmw/jnitest/MainActivity);//获取属性的fieldId--》这里就用到了签名类型 jfieldID ageFid env-GetFieldID(mainActivityCls,age,I); jfieldID nameFidenv-GetFieldID(mainActivityCls, name, Ljava/lang/String;); //获取属性值 jint age env-GetIntField(mainActivityThis,ageFid); jstring name (jstring)env-GetObjectField(thiz,nameFid);//此处有编码转换问题未解决//修改属性值C中修改变量值后Java重新获取打印发现是修改过的 env-SetIntField(mainActivityThis, ageFid , 11); env-SetObjectField(thiz, nameFid,Stringvalue);//获取方法的methodId--》这里就用到了签名类型 jmethodID addMidenv-GetMethodID(mainActivityCls, add, (II)I); int resultenv-CallIntMethod(mainActivityThis, addMid, 1, 1); //这里就能获取到2的值。 仔细看一下上面的代码就大致能理解这个签名表格的具体作用为了找到Java方法的参数和返回值的形式。 Java签名类型小结 1基础类型签名那些转换都是很容易记住的基础类型中特别留意一下boolean类型 是 Z 就行 2对象Object类型的转换是L全包名包名直接用 /间隔类名分号 3数组类型签名转换[数组类型比如[I,表示Java的 int[]4方法签名的转换(参数类型)返回类型,中间多个参数类型依此填写就行 比如Jni中的代码env-GetMethodID(add, (IILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;) 如果不清楚上面的表格转换看起来就头大,特别是那些有三四个以上参数的情况但是学习过后就不难了 查看表格对应关系可以知道Java中的对应方法是public String add(int a,int b,String c,String d) 其实就是先看括号后面的返回值然后再一个个确定括号内的形参变量共勉 这短短的一生我们最终都会过去你不妨大胆一些爱一个人、攀一座山、追一个梦
http://www.hkea.cn/news/14505219/

相关文章:

  • 没有网站可以做seo吗erp沙盘模拟实训报告
  • 上海史特网站建设微信支付申请网站建设未完成
  • 个人网站开发意义旅游网站首页设计大概图
  • 百度怎么建立自己的网站网络推广培训班哪家好
  • 工程公司有哪些广州seo网站营销
  • 免费的网页网站网站内页权重查询
  • 制作企业网站的西安租房网
  • 自己的电脑做网站空间视屏西湖专业网站设计公司
  • 西北建设有限公司网站微信商家小程序收费吗
  • 建网站书籍海口旅游类网站建设
  • 安徽住房和城乡建设厅注册网站天津全包圆装饰公司官网
  • 电销做网站的话术大连网站建设流程图
  • 网站大全免费完整版营销型网站制作成都
  • 苏州关键词网站排名排名优化哪家专业
  • 制作网站首页教案建立个人网站的目的
  • 网站服务器物理地址怎么查万博法务网站建设项目
  • 深圳网站建设公司首选学生网页设计主题
  • 公司网站建设佛山哪家好莱芜网站建设优化
  • 网站建设与开发 期末作品懒人手机网站模板
  • 商业网站页面万网域名申请网站
  • 淄博品先网络科技有限公司宁波seo整体优化公司
  • 逻辑图在线制作网站建微信网站模板
  • 国外网站无法访问网站开发编程环境
  • 电子商务网站建设公司开公司怎么找客户
  • 郑州网站优化汉狮网络网站开发项目教程笔记
  • 我想做个网站怎么做的电子商务网站建设与管理的论文总结
  • 优秀设计工作室网站戴尔的网站建设
  • 建筑网站首页杭州赛虎网站建设
  • 网站建设与维护工作wordpress主机 seo
  • 网站建设的业务范围dw网页设计与制作