精华内容
下载资源
问答
  • 2021-02-27 11:40:30

    可以通过JNI从Java调用的每个C函数都有一个JNIEnv *类型的第一个参数.在C端,这是一个指向具有多个函数指针的结构的指针.这些功能是您与Java世界的接口. FindClass,GetMethodID和其余的都在其中.

    因此,当您想从C端调用FindClass时,方法如下:

    void Java_com_mypackage_MyClass_MyMethod(JNIEnv *jniEnv, jobject thiz)

    {

    jclass *clazz = (*(*jniEnv)->FindClass)(jniEnv, "com/mypackage/SomeClass");

    jmethodID MethodID = (*(*jniEnv)->GetStaticMethodID)(jniEnv, clazz, "SomeMethod", "(I)I");

    int result = (*(*jniEnv)->CallStaticIntMethod)(jniEnv, clazz, MethodID, 18);

    依此类推.该行取消了jniEnv参数的引用,获取了一个函数指针,并通过它调用了函数.自然,类和方法名完全是伪造的.我怎么知道你的

    注意:我在这里说的是函数指针,但与您的意思不同.这些是指向JNI提供的功能的函数指针,而不是指向您的函数的函数指针.

    调用语法的冗长程度与C的局限性有关.在C中,您可以改写

    jclass *cl = jniEnv->FindClass("com/mypackage/SomeClass");

    因为C通过虚拟函数本地支持这种函数表指针.

    您可能会沿途采取一些捷径.如果要在与C入口点相同的类中调用方法,并且它恰好是静态的,则第二个参数已经是类对象指针.如果您具有要在其上调用方法的对象的this指针,则可以使用GetObjectClass.

    更多相关内容
  • 1、ndk层修改java层的对象的成员 package com.yuanxuzhen.testnative; public class UserData { public String name; public String sex; public int age; public UserData(String name, String sex, int ...

    1、ndk层修改java层的对象的属性

    package com.yuanxuzhen.testnative;
    
    public class UserData {
        public String name;
        public String sex;
        public int age;
    
        public UserData(String name, String sex, int age) {
            this.name = name;
            this.sex = sex;
            this.age = age;
        }
    
        public UserData(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "UserData{" +
                    "name='" + name + '\'' +
                    ", sex='" + sex + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
     public native UserData callNativeUserData(UserData data);
    JNIEXPORT jobject JNICALL
    Java_com_yuanxuzhen_testnative_MainActivity_callNativeUserData(JNIEnv *env, jobject thiz,
                                                                   jobject data) {
        // TODO: implement callNativeUserData()
        jclass  cls = (*env)->GetObjectClass(env, data);
        jfieldID jfieldId = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
        jstring jstring1 = ((*env)->GetObjectField(env, data, jfieldId));
        const char* c = (*env)->GetStringUTFChars(env,jstring1, 0);
        LOGE("native name = %s", c );
        (*env)->ReleaseStringUTFChars(env,jstring1, c);
    
        jstring jstring2 = (*env)->NewStringUTF(env,"yuanping");
        (*env)->SetObjectField(env,data, jfieldId, jstring2);
        return data;
    }

    2、ndk层访问java层的静态方法

        public static void testStaticJniCallJava(String name){
            Log.e("xxxx", "testJniCallJava name="+name);
        }
    
     public native void jniCallJava();
    
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
            jniCallJava();
    
        }
    JNIEXPORT void JNICALL
    Java_com_yuanxuzhen_testnative_MainActivity_jniCallJava(JNIEnv *env, jobject thiz) {
        jclass cls = (*env)->GetObjectClass(env, thiz);
        jmethodID  jmethodId = (*env)->GetStaticMethodID(env, cls, "testStaticJniCallJava", "(Ljava/lang/String;)V");
        (*env)->CallStaticVoidMethod(cls, jmethodId, (*env)->NewStringUTF(env,"yuanjingyao"));
    }
    

    thiz代表调用的对象

    3、ndk层调用对象的方法

    public native void callInterface(ITest test);
    //extern "C"
    JNIEXPORT void JNICALL
    Java_com_yuanxuzhen_testnative_MainActivity_callInterface(JNIEnv *env, jobject thiz, jobject test) {
        LOGE("callInterface 1111111");
    
        jclass cls = (*env)->GetObjectClass(env, test);
        jmethodID methodId = (*env)->GetMethodID(env,cls, "printUserData",
                                              "(Lcom/yuanxuzhen/testnative/UserData;)V");
        jstring name = (*env)->NewStringUTF(env,getYuanxzh());
        jstring sex = (*env)->NewStringUTF(env, "female");
        jint age = 2;
        jclass userDataClass =  (*env)->FindClass(env,"com/yuanxuzhen/testnative/UserData");
        jmethodID useGenId = (*env)->GetMethodID(env,userDataClass, "<init>",
                                              "(Ljava/lang/String;Ljava/lang/String;I)V");
    
        jobject useObject = (*env)->NewObject(env,userDataClass, useGenId, name, sex, age);
    
        (*env)->CallVoidMethod(env,test, methodId, useObject);
    
        LOGE("callInterface 222222");
    
    }

    4、ndk层创建java层对象

        jclass userDataClass =  (*env)->FindClass(env,"com/yuanxuzhen/testnative/UserData");
        jmethodID useGenId = (*env)->GetMethodID(env,userDataClass, "<init>",
                                              "(Ljava/lang/String;Ljava/lang/String;I)V");
    
        jobject useObject = (*env)->NewObject(env,userDataClass, useGenId, name, sex, age);
    
        (*env)->CallVoidMethod(env,test, methodId, useObject);

    5 ndk 层方法调用java接口

    public interface ITest {
         void printUserData(UserData data);
    }
     public native void callInterface(ITest test);
    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
            binding.sampleText.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    callInterface(new ITest() {
                        @Override
                        public void printUserData(UserData data) {
                            Log.e("xxxx", "printUserData data = " + data);
                        }
                    });
                }
            });
    
        }
    Java_com_yuanxuzhen_testnative_MainActivity_callInterface(JNIEnv *env, jobject thiz, jobject test) {
        LOGE("callInterface 1111111");
    
        jclass cls = (*env)->GetObjectClass(env, test);
        jmethodID methodId = (*env)->GetMethodID(env,cls, "printUserData",
                                              "(Lcom/yuanxuzhen/testnative/UserData;)V");
        jstring name = (*env)->NewStringUTF(env,getYuanxzh());
        jstring sex = (*env)->NewStringUTF(env, "female");
        jint age = 2;
        jclass userDataClass =  (*env)->FindClass(env,"com/yuanxuzhen/testnative/UserData");
        jmethodID useGenId = (*env)->GetMethodID(env,userDataClass, "<init>",
                                              "(Ljava/lang/String;Ljava/lang/String;I)V");
    
        jobject useObject = (*env)->NewObject(env,userDataClass, useGenId, name, sex, age);
    
        (*env)->CallVoidMethod(env,test, methodId, useObject);
    
        LOGE("callInterface 222222");
    
    }

    从上面可以知道java层的接口到了ndk层就成了对象

    6、ndk层调用java的构造函数

    jclass userDataClass =  (*env)->FindClass(env,"com/yuanxuzhen/testnative/UserData");
        jmethodID useGenId = (*env)->GetMethodID(env,userDataClass, "<init>",
                                              "(Ljava/lang/String;Ljava/lang/String;I)V");
    
        jobject useObject = (*env)->NewObject(env,userDataClass, useGenId, name, sex, age);
    

    展开全文
  • ndkC调用java方法以及动态注册

    千次阅读 2022-01-30 16:53:15
    ndk开发需要在java层和native层相互调用代码,如何确定native方法与jni函数之间的映射关系呢?这就涉及到jni函数的注册,注册方式有两种:静态注册和动态注册。 静态注册采用基于约定的命名规则(Java_开头,后接类...

    一、静态注册和动态注册

    ndk开发需要在java层和native层相互调用代码,如何确定native方法与jni函数之间的映射关系呢?这就涉及到jni函数的注册,注册方式有两种:静态注册和动态注册。
    静态注册采用基于约定的命名规则(Java_开头,后接类的全限定名加下划线,方法名这三个组成部分组成,如下代码所示),可以通过javah或IDE自动生成native方法对应的函数声明。
    优点是简单;缺点是不灵活,修改java类名或jni方法名时,需要同步修改对应的native函数命名。

    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_shan_dynamicndk_MainActivity_jniCallAdd(JNIEnv *env, jobject thiz, jint num1, jint num2) {
        // TODO: implement jniCallAdd()
    }
    

    动态注册通过JNINativeMethod函数和JNI_OnLoad函数的编辑可以在native代码中自由定义jni函数与native函数的映射。优点是灵活,缺点可能会由于无法使用javah和IDE自动补全功能而相对麻烦些。

    二、C代码调用java代码(静态注册)

    以native层调用java层方法获取uuid的方法为例
    java层代码MainActivity.java如下

    //MainActivity.java
    package com.shan.ndkapp;
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.TextView;
    import com.shan.ndkapp.databinding.ActivityMainBinding;
    import java.util.UUID;
    
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "ndk_test_java";
    
        // Used to load the 'ndkapp' library on application startup.
        static {
            System.loadLibrary("ndkapp");
        }
    
        private ActivityMainBinding binding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
    
            // Example of a call to a native method
            TextView tv = binding.sampleText;
            tv.setText(getUUidFromJava());
        }
    
    
        public String getUuid() {
            String uuid = UUID.randomUUID().toString();
            Log.d(TAG, "getUuid:"+uuid);
            return uuid;
        }
    
        public native String getUUidFromJava();
    }
    
    

    native层代码native-lib.cpp如下:

    //native-lib.cpp
    #include <jni.h>
    #include <string>
    #include <android/log.h>
    #define  LOG_TAG  "ndk_test_c"
    #define LOGD(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    
    extern "C"
    JNIEXPORT jstring JNICALL
    Java_com_shan_ndkapp_MainActivity_getUUidFromJava(JNIEnv *env, jobject thiz) {
        // TODO: implement getUUidFromJava()
        jclass  j_class = env->GetObjectClass(thiz);//根据jobject获取jclass
        jmethodID j_methodId = env->GetMethodID(j_class,"getUuid","()Ljava/lang/String;");//最后一个参数方法签名可以通过javap -s className得到
        jobject j_uuid = env->CallObjectMethod(thiz, j_methodId);
        const char* uuid = env->GetStringUTFChars(static_cast<jstring>(j_uuid),NULL); //jstring转化为char*才可以在C语言打印
        LOGD("Java_com_shan_ndkapp_MainActivity_getUUidFromJava,uuid=%s",uuid);
        env->ReleaseStringUTFChars(static_cast<jstring>(j_uuid),uuid); //回收字符串
        return static_cast<jstring>(j_uuid);
    }
    

    上面native代码的第13行获取方法签名时,如果忘记了签名规则,可以在当前工程目录下面找到
    build/intermediates/javac/debug/classes/com/shan/ndkapp/MainActivity.class,在该目录下打开命令行,通过javap -s MainActivity.class获取该类所有签名信息。

    三、动态注册

    以java层调用native层代码获取字符串以及native层代码调用java层add函数为例,这两个函数都采用动态注册实现。
    java代码MainActivity.java如下

    //MainActivity.java
    package com.shan.dynamicndk;
    
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    import com.shan.dynamicndk.databinding.ActivityMainBinding;
    
    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'dynamicndk' library on application startup.
        static {
            System.loadLibrary("dynamicndk");
        }
    
        private ActivityMainBinding binding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
    
            // Example of a call to a native method
            TextView tv = binding.sampleText;
            tv.setText(stringFromJNI()+":"+jniCallAdd(2,3));
        }
    
        public int add(int num1,int num2) {
            return num1+num2;
        }
    
        /**
         * A native method that is implemented by the 'dynamicndk' native library,
         * which is packaged with this application.
         */
        public native String stringFromJNI();
        public native int jniCallAdd(int num1,int num2);
    }
    

    native层代码如下

    #include <jni.h>
    #include <string>
    
    extern "C" JNIEXPORT jstring JNICALL
    c_getString(
            JNIEnv* env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    
    extern "C" JNIEXPORT jint JNICALL
    c_callAdd(
            JNIEnv* env,
            jobject  thiz,jint num1, jint num2) {
        jclass  j_class = env->GetObjectClass(thiz);//根据jobject获取jclass
        jmethodID j_methodId = env->GetMethodID(j_class,"add","(II)I");//最后一个参数方法签名可以通过javap -s className得到
        jint j_add = env->CallIntMethod(thiz, j_methodId,num1,num2); //调用java层的add方法
        return j_add;
    }
    
    static JNINativeMethod methods[] = {
            { "stringFromJNI", "()Ljava/lang/String;", (void*)c_getString},
            { "jniCallAdd", "(II)I", (void*)c_callAdd},
    };
    
    JNIEXPORT jint JNICALL
    JNI_OnLoad(JavaVM* vm, void* reserved) {
        JNIEnv *env = NULL;
    
        // 获取JNI env变量
        if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
            // 失败返回-1
            return JNI_ERR;
        }
    
        // 获取native方法所在类
        jclass clazz = env->FindClass("com/shan/dynamicndk/MainActivity"); //包名类名必须完全一致,否则匹配失败
        if (clazz == NULL) {
            return JNI_ERR;
        }
    
        // 动态注册native方法
        if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
            return JNI_ERR;
        }
    
        // 返回成功
        return JNI_VERSION_1_6;
    }
    

    动态注册分为三步:1、定义JNINativeMethod结构体确定映射关系 2、调用JNI_OnLoad函数去加载 3、具体实现native函数。
    JNINativeMethod结构体中记录了java层函数名称name、函数签名signature以及native层代码的函数指针fnPtr,JNINativeMethod结构体定义在jni.h中,有兴趣的话可以查看一下jni.h文件。

    //jni.h
    typedef struct {
        char *name;
        char *signature;
        void *fnPtr;
    } JNINativeMethod;
    
    
    展开全文
  • android NDK(java调用C)

    2016-11-15 09:54:35
    java调用C的方法 相关博客http://blog.csdn.net/lang523493505/article/details/53163679
  • JavaCallCJNI/NDK java调用c开发流程1、在java写native代码public class JNI {{System.loadLibrary("app");}/***定义native代码* 调用C代码对于的方法* com.loadingbar.demo.demondk.JNI#sayHello()* @return*/...

    JavaCallC

    JNI/NDK java调用c

    开发流程

    1、在java写native代码

    public class JNI {

    {

    System.loadLibrary("app");

    }

    /**

    *定义native代码

    * 调用C代码对于的方法

    * com.loadingbar.demo.demondk.JNI#sayHello()

    * @return

    */

    public native String sayHello();

    /**

    * 让c代码做加法运算,把结果返回

    * @param x

    * @param y

    * @return

    */

    public native int add(int x,int y);

    /**

    *从java传入字符串,c代码拼接后返回

    * @param s

    * @return

    */

    public native String sayHi(String s);

    /**

    * 让C代码给数组的每个元素加上10

    * @param array

    * @return

    */

    public native int[] increaseArrayEles(int[] array);

    /**

    * c代码检查密码是否正确 正确返回200 错误返回400

    * @param pwd

    * @return

    */

    public native int checkPwd(String pwd);

    }

    2、生成头文件.h

    在AS下Terminal进入到app/src/main/java下,使用命令javah+全类名生成头文件

    3、配置动态链接库的名称

    ndk{

    moduleName "Hello" //so文件:lib+moduleName+.so

    abiFilters "armeabi","armesbi-v7a","x86" //cpu的类型

    }

    4、加载动态链接库

    {

    System.loadLibrary("app");

    }

    5、调用

    展开全文
  • JNI之java调用c库简单实例

    千次阅读 2022-01-17 14:23:57
    因为架构迁移或者开发需要,有时候需要在android应用开发中,调用已有的c语言开发库,此时可能需要用到JNI。
  • 如果安装不了NDK可以看这篇文章:android-ndk-aide,NDK安装教程20180605 步骤: 注:我编写的应用包名为"com.nativeapp",文件路径为"/sdcard/AppProjects/Nativeapp" 1、编写一个java(需带有native声明) Native...
  • 详情请参考我的博客 http://blog.csdn.net/allen315410/article/details/41862479
  • 安装Cygwin解压android-ndk-r5c-windows.zip解压cygwin package.rarCygwin安装步骤运行setup.exe,选第三项从本地安装cygwin设置cygwin安装到那里指定安装程序位置选中安装的内容,只选devel就可以了cygwin与Ndk集成...
  • NDK开发(三)——C/C++代码如何调用java层代码 E:\AndroidProject\TheTestPro\NDKDemo\app\build\intermediates\javac\debug\classes>javap -s -p com.lwp.ndkdemo.MainActivity Compiled from "MainActivity....
  • android中的java依托于java虚拟机,运行效率是比较低的,最近在做高效大数乘法中,发现了JNI或者NDK可以实现CJava混编,并且引用c的动态库,而且android中的C语言不需要依托java虚拟机,效率还是非常高的。...
  • NDK_C调用java demo

    2015-09-24 14:53:45
    NDK使用C代码调用java中的方法事例demo
  • 详细介绍了NDK开发中C语言如何获取java层对象的属性,如何调用java层的方法。
  • 安卓JAVA JNI NDK 基础使用样例 附实现的详细步骤开发环境实现步骤 最近做安卓项目需要使用到JNI的知识调用C文件,在网上搜寻了近两天的资料踩了很坑,总结了一套在安卓中使用JNI的步骤,记录在这里顺便提供给像我...
  • Android JNI 和 NDK

    2021-02-28 17:11:31
    JNI (Java Native Interface) 和 NDK (Native Development Kit):jni 是java调用...jni 的目的是java调用c、c++写的本地方法;android下是用JNI时需要的.so文件,是通过ndk-build生成的。Java Native Interface(J...
  • ndk开发,在c调用java中的代码
  • JNI(Java Native Interface):java本地开发接口,JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(c/c++),外部的c/c++代码也可以调用java代码。我们为什么要使用JNI呢,可以从效率和安全性两方面...
  • 一、Java调用C++方法
  • NDKJAVAC互相调用

    2013-04-07 15:38:29
    JAVA调用C, C调用JAVA创建一个按钮 这个按钮点击后,又调用一个C函数 改编自NDK例子
  • 自己在android studio 环境下集成ndk 、 cmake 、LLDB 等插件 开发的一个demo ; 可以直接debug到c端代码,eclipse一般追踪不到,遇到c端出问题手机直接一个crash,,,想要了解android studio 下如何进行c 开发的...
  • 简书链接 在平时的NDK开发中,我们通常使用C/C++封装好so库,然后客户端调用so库以完成我们的需求,在上一遍入门中(NDK开发之初入门-Hello Word)我们在So库方法中实现返回字符串Hello Word,然后在Java中进行...
  • Android Studio NDK开发-JNI调用Java方法 相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就...
  • 安卓app开发之NDK入门教程,JAVA代码通过JNI接口调用NDK代码(C语言编写的linux android功能).zip
  • Android NDK Java 调用C

    2011-09-26 18:19:23
    Android NDK Java 调用C~~~~~~~~~~~~~
  • 学习NDK开发的过程中查找了很多资料很多博客,也实验了很多次,觉得还是自己整理一下比较好。省略部分:添加一个button设置监听用于调用native方法。。。开始—– 1、先配置一下NDK环境 2、添加一个专门放...
  • NDK开发之C语言调用Java构造方法、父类方法、返回中文字符串乱码问题案例详细解析。
  • 在本教程中,您将在Java中创建一个图像处理应用程序,并通过NDK使用C代码执行基本的图像处理操作。首先,了解Android原生开发工具包(NDK)的动机之一是得以利用开源项目,大多数项目都是用C语言编写的。完成本教程...
  • 在Android Studio3.3版本后 ,我们直接就可以调用C语言 如图: 定义方法: 方法内写C就ok了
  • Android NDK 调用C

    2021-06-05 18:30:13
    一.环境准备:1.Cygwin:对于网速较慢的孩子,可以直接下载一个简约版:http://www.wishdown.com/soft/52987.html2.安装完毕后(笔者安装路劲为:E:\Android\Cygwin\setup)1) 修改 E:\...profile增加2行:NDK=/cygdri...
  • 首先下载好对应的NDK,解压目录配置到...ndk.dir=C\:\\Users\\aibo\\AppData\\Local\\Android\\Sdk\\ndk-bundle sdk.dir=C\:\\Users\\aibo\\AppData\\Local\\Android\\Sdk 方式一: 新建项目时选择最后一个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,121
精华内容 14,448
关键字:

java调用c ndk

java 订阅