NDK-CPP语言-指针引用+函数指针+函数重载

46 篇文章 1 订阅
43 篇文章 0 订阅
public class NDKCInterface {

    public native void executeCConst();

}


public class NDKCppInterface {

    //1.学习C++中的常量(包括和C中的常量的区别)
    public native void executeCppConst();

    //2.C++指针的引用
    public native void executeCppPointer();

    //3.C++常引用
    public native void executeCppConstRef();

    //4.C++内联函数
    public native void executeCppInlineFunc();

    //5.C++函数参数
    public native void exceuteCppFuncParam();

    //6.C++函数指针
    public native void exceuteCppFuncPointer();

    //7.C++中的类的定义
    public native void executeCppClass();
}

com_tz_ndk_cpp_NDKCInterface.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_tz_ndk_cpp_NDKCInterface */

#ifndef _Included_com_tz_ndk_cpp_NDKCInterface
#define _Included_com_tz_ndk_cpp_NDKCInterface
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_tz_ndk_cpp_NDKCInterface
 * Method:    executeCConst
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCInterface_executeCConst
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


com_tz_ndk_cpp_NDKCInterface.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <android/log.h>
#include "com_tz_ndk_cpp_NDKCInterface.h"

//C语言中常量是否可以修改
//C语言中也不能修改 
//总结:常量的值在C语言中是可以修改的,但是与编译的环境有关系
//例如:在android studio中不可以,在Visual Studio 2013就可以修改
//然而C++语言不管在任何的编译环境中都是不允许修改
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCInterface_executeCConst
        (JNIEnv *env, jobject jobj){
    const int a = 100;
    int *p = (int*)&a;
    *p = 200;
    __android_log_print(ANDROID_LOG_INFO,"main","C语言:%d",a);
}
com_tz_ndk_cpp_NDKCppInterface.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_tz_ndk_cpp_NDKCppInterface */

#ifndef _Included_com_tz_ndk_cpp_NDKCppInterface
#define _Included_com_tz_ndk_cpp_NDKCppInterface
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_tz_ndk_cpp_NDKCppInterface
 * Method:    executeCppConst
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppConst
  (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppPointer
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppConstRef
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppInlineFunc
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_exceuteCppFuncParam
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_exceuteCppFuncPointer
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppClass
        (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

com_tz_ndk_cpp_NDKCppInterface.cpp

#include <iostream>
#include <android/log.h>
#include "com_tz_ndk_cpp_NDKCppInterface.h"

//在C++中命名空间(类似于Java的包)
//std:代表标准命名空间
using namespace std;

//C++中常量
//C++中常量的值不能够修改(不管你是间接修改还是直接修改,都不是不允许)
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppConst
    (JNIEnv *env, jobject jobj){
    const int a = 100;
    //常量不能修改
//    a = 200;
    //间接修改
    int *p = (int*)&a;
    *p = 200;
    __android_log_print(ANDROID_LOG_INFO,"main","修改值:%d",a);
}


//2.指针的引用
struct User{
    char *name;
    int age;
};

//二级指针
//void update_user(User** u){
//    User *user = (User*)malloc(sizeof(User));
//    user->name = "Dream";
//    user->age = 100;
//    *u = user;
//}
//指针的引用
//&u代表是User地址(相当于引用)
void update_user(User* &u){
    u = (User*)malloc(sizeof(User));
    u->name = "Crish";
    u->age = 18;
}

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppPointer
        (JNIEnv *env, jobject jobj){
    User *user = NULL;
    //二级指针的使用
//    int a = 100;
//    int *p = &a;
//    int **p2 = &p;
//    update_user(&user);
//    __android_log_print(ANDROID_LOG_INFO,"main","result: %s",user->name);

    //指针的引用
    int a = 100;
//    (int*) p = &a;
    //编译器自动将 user转成&user
    update_user(user);
    __android_log_print(ANDROID_LOG_INFO,"main","result: %s",user->name);
}


//C++中的常引用(初始化方式)
void const_init(){
    int a = 100;
    int b = 200;
    //第一种写法:变量赋值
    //常引用写法:const int &c
    //引用:&c

    //我们这么写: int &c = a;
    //int &c = a;等价int* c = &a;
    //编译器:int* c = &a;
    const int &c = a;
    __android_log_print(ANDROID_LOG_INFO,"main","变量赋值:%d",c);

    //第二种写法:字面量
    const int &d = 200;
    __android_log_print(ANDROID_LOG_INFO,"main","字面量: %d\n",d);
}
//重点是:常引用作为函数的参数使用
struct Company{
    char *name;
    char *address;
    int age;
};

//类似于Java中的final(只读)
void const_func_param(const Company &cp){
    //不能修改(只读)
//    cp.age = 100;
    __android_log_print(ANDROID_LOG_INFO,"main","公司地址: %s",cp.address);
}

void const_printf(){
    Company company;
    company.address = "湖南省芯城科技园10栋";
    company.name = "潭州教育科技有限公司";
    company.age = 10;
    const_func_param(company);
}
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppConstRef
        (JNIEnv *env, jobject jobj){
//    const_init();
    const_printf();
}




//4.内联函数(inline)
//在程序编译的时候,编译器将函数调用处的代码替换成函数体
//内联函数:编译的时候调用
//宏定义:预编译
//例如:买书
//买书之前准备钱(预编译)
//找书店过程(编译)
//找到了书店,买书(运行)
//在使用上面和普通的函数没什么区别,但是执行的效率比一般的函数要高
inline void printf_inline(){
    char *address = "Dream";
    __android_log_print(ANDROID_LOG_INFO,"main","内容:%s",address);
}

//宏定义和内联函数的区别?
//需求:求一个数的积?
//总结:这两种情况一般情况都不要这么写(自增、自减)
#define GET_RESULT(A) A*A

inline int get_result(int a){
    return a * a;
}

void printf_result(){
    int a = 2;
    //宏函数预编译替换
    //分析:int b = (++a) * (++a)
    //第一次加:a = 3  * (++a)
    //第二次加:a = 4
    //结果: 3 * 4 = 12;
//    int b = GET_RESULT(++a);

    //内联函数(和普通的方法一样)
    //结果:a * a ,然而a = 3  结果:9
    int b = get_result(++a);

    __android_log_print(ANDROID_LOG_INFO,"main","结果:%d",b);
}

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppInlineFunc
        (JNIEnv *env, jobject jobj){
    //拷贝(编译的时候)
//    {
//        char *address = "Dream";
//        __android_log_print(ANDROID_LOG_INFO,"main","内容:%s",address);
//    }
//    printf_inline();
    printf_result();
}


//5.C++中函数参数
//函数参数默认值
//void func_param(int a = 100){
//    __android_log_print(ANDROID_LOG_INFO,"main","result: %d",a);
//}

//函数重载(在Java中方法重载:参数个数,参数类型不同,与返回值无关)
//总结:定义函数重载需要注意不能够存在函数"歧义"
//void func_param(int a){
//    __android_log_print(ANDROID_LOG_INFO,"main","result: %d",a);
//}
//void func_param(int a,int b = 10){
//    __android_log_print(ANDROID_LOG_INFO,"main","result: a=%d, b=%d",a,b);
//}

//b默认值,后面的参数必须设置默认值
//void func_param(int a,int b){
//    __android_log_print(ANDROID_LOG_INFO,"main","result: %d",a);
//}
//void func_param(int a,int b = 10,int c = 10,int d = 100){
//    __android_log_print(ANDROID_LOG_INFO,"main","result: %d",a);
//}

//C++中函数可变参数
//API都会提示用户传参数类型
void func_param(int a,...){
    __android_log_print(ANDROID_LOG_INFO,"main","result: %d",a);
    //获取可变参数
    //定义可变参数指针
    va_list args_p;
    //首先指定可变参数开始位置
    va_start(args_p,a);
    //一个个获取(按照顺序读取)
    //第一个参数int类型
    int arg_int = va_arg(args_p,int);
    __android_log_print(ANDROID_LOG_INFO,"main","第一个参数: %d",arg_int);
    //第二个参数char类型
    char arg_char = va_arg(args_p,char);
    __android_log_print(ANDROID_LOG_INFO,"main","第二个参数: %c",arg_char);
    //第三个参数double类型
    double arg_float = va_arg(args_p, double);
    __android_log_print(ANDROID_LOG_INFO,"main","第三个参数: %f",arg_float);
    //结束
    va_end(args_p);

}

//循环读取(一般情况下都是指定类型)
//注意:必须要指定一个可变参数开始位置
void func_param_int(int a,int len,...){
    //定义可变参数指针
    va_list args_p;
    //首先指定可变参数开始位置
    va_start(args_p,len);

    int i = 0;
    int result = 0;
    for(;i < len ;i++){
        result = va_arg(args_p,int);
        __android_log_print(ANDROID_LOG_INFO,"main","参数: %d",result);
    }

//    int i = 0;
//    while (true){
//        i = va_arg(args_p,int);
//        if(i == 0){
//            //告诉程序读取完毕
//            break;
//        }
//        __android_log_print(ANDROID_LOG_INFO,"main","参数: %d",i);
//    }
    //结束
    va_end(args_p);
}

//函数预留参数(提高了程序扩展性)
void func_param(int a,int){
    __android_log_print(ANDROID_LOG_INFO,"main","参数: %d",a);
}

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_exceuteCppFuncParam
        (JNIEnv *env, jobject jobj){
//    func_param();
//    func_param(10);
//    func_param(10,20);
    //歧义?
//    func_param(10);
//    func_param(10,20);
//    func_param(10,40,'A',45.3);
//    func_param_int(10,5,20,30,40,50,60);
    func_param(10,20);
}

//6.函数指针
int get_min(int a,int b,int c,int d){
    return a < b ? a : b;
}
//函数指针别名
typedef int(*GET_MIN_P)(int,int,int,int);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_exceuteCppFuncPointer
        (JNIEnv *env, jobject jobj){
    //函数指针
//    int(*get_min_p)(int,int,int,int) = get_min;
//    int c = get_min_p(10,20,20,30);
//    __android_log_print(ANDROID_LOG_INFO,"main","最小值: %d",c);

    GET_MIN_P p = get_min;
    int result = p(10,20,30,40);
    __android_log_print(ANDROID_LOG_INFO,"main","最小值: %d",result);
}


//7.C++中的类的定义
#include "Computer.h"

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCppInterface_executeCppClass
        (JNIEnv *, jobject){
//    Computer computer;
//
//    computer.setCPU("Inter");
//    computer.setDisplay("独立显卡");
//    computer.setName("Macbook Pro 2016款");
//    computer.setAge(6);
//    __android_log_print(ANDROID_LOG_INFO,"main","显卡: %s",computer.getDisplay());

    //也可以new
    Computer* computer = new Computer();
    computer->setAge(100);
    computer->setDisplay("独立显卡");
    __android_log_print(ANDROID_LOG_INFO,"main","显卡: %s",computer->getDisplay());
}

Computer.h

//这个判断就是为了避免重复include
#ifndef DREAM_NDK_CPP_11_3_COMPUTER_H
#define DREAM_NDK_CPP_11_3_COMPUTER_H

//申明该类
class Computer{
private:
    char *cpu;
    char *display;
    char *name;
    int age;
public:
    void setCPU(char* cpu);
    char* getCPU();
    void setDisplay(char* display);
    char* getDisplay();
    void setName(char *name);
    char* getName();
    void setAge(int age);
    int getAge();

};

#endif //DREAM_NDK_CPP_11_3_COMPUTER_H

Computer.cpp

#include <iostream>
#include "Computer.h"


void Computer::setCPU(char *cpu) {
    this->cpu = cpu;
}

char *Computer::getCPU() {
    return this->cpu;
}

void Computer::setDisplay(char *display) {
    this->display = display;
}

char *Computer::getDisplay() {
    return this->display;
}

void Computer::setName(char *name) {
    this->name = name;
}

char *Computer::getName() {
    return this->name;
}

void Computer::setAge(int age) {
    this->age = age;
}

int Computer::getAge() {
    return this->age;
}


activity:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    private NDKCppInterface cppInterface;
    private NDKCInterface cInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        cppInterface = new NDKCppInterface();
        cInterface = new NDKCInterface();

        String a = new String("Dream");
        get(a,10,30,200,300);

    }

    private void get(String s,int... a){
        s = "100";

    }

    public native String stringFromJNI();

    public void clickCppConst(View v){
        cppInterface.executeCppConst();
    }

    public void clickCConst(View v){
        cInterface.executeCConst();
    }

    public void clickCppPointer(View v){
        cppInterface.executeCppPointer();
    }

    public void clickCppConstRef(View v){
        cppInterface.executeCppConstRef();
    }

    public void clickCppInlineFunc(View v){
        cppInterface.executeCppInlineFunc();
    }

    public void clickCppFuncParam(View v){
        cppInterface.exceuteCppFuncParam();
    }

    public void clickCppFuncPointer(View v){
        cppInterface.exceuteCppFuncPointer();
    }

    public void clickCppClass(View v){
        cppInterface.executeCppClass();
    }

}


配置文件:CMakeLists.txt

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/native-lib.cpp
             src/main/cpp/com_tz_ndk_cpp_NDKCppInterface.cpp
             src/main/cpp/com_tz_ndk_cpp_NDKCInterface.c
             src/main/cpp/Computer.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )


整理自示例代码





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值