Android JNI学习入门之使用C++链表结构存储数据

本文介绍了一个使用NDK在AndroidStudio中构建链表的例子,通过Java和C/C++互相调用的方式,实现数据的存储和检索功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  学习NDK开发,一方面是掌握Java和C/C++互相调用,另一方面是掌握C/C++语言本身的基础;因此我觉得入门的最好方式就是使用C/C++构建数据结构,然后存储数据;这样既可以掌握一些C++语言本身的基础知识,又可以掌握一些Java和C/C++对象的互相调用的方法。
  本次项目是在Android Studio中构建的。
  首先,我新建一个Java类,
public class LinkList {

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

    public LinkList(){
        init();
    }
    public native void  init();
    public native void  add(int key,String value);
    public native int size();
    public native Node next();
    public native void prenext();
    public native boolean hasnext();
    public native String get(int key);
}

然后在cpp文件中新建和它对象的h文件


#include "jni.h"
#include "list.h"
#include <stdlib.h>
#include <string>


#ifndef JNIEXAMPLE_NATIVE_LINKLIST_H
#define JNIEXAMPLE_NATIVE_LINKLIST_H
extern "C"{


using namespace std;

Node *startNode= nullptr,*endNode= nullptr,*nextNode= nullptr;
int count=0;


JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_init(JNIEnv *,jobject);
JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_add(JNIEnv *,jobject,jint ,jstring);
JNIEXPORT jint JNICALL Java_com_xuye_xy_socket_jni_LinkList_size(JNIEnv *,jobject);
JNIEXPORT jobject JNICALL Java_com_xuye_xy_socket_jni_LinkList_next(JNIEnv *,jobject);

JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_prenext(JNIEnv *,jobject);

JNIEXPORT jboolean JNICALL Java_com_xuye_xy_socket_jni_LinkList_hasnext(JNIEnv *,jobject);
JNIEXPORT jstring JNICALL Java_com_xuye_xy_socket_jni_LinkList_get(JNIEnv *,jobject,jint);
jobject newNode(JNIEnv *env,int key, const char *value);

};

这个是Node类如下:

#include "jni.h"
#ifndef JNIEXAMPLE_LIST_H
#define JNIEXAMPLE_LIST_H
extern  "C"{

class Node{
public:
    Node *next,*pre;
    Node(){
        this->key=0;
        this->value= nullptr;
    };
    Node(int key, const char* value){
        this->key=key;
        this->value=value;
    };
    ~Node(){};

    int getkey(){
        return this->key;
    }
    const char* getvalue(){
        return this->value;
    };
    void set(int key, const char* value){
        this->key=key;
        this->value=value;
    }

private:
    int key;
    const char *value;
};
};
#endif //JNIEXAMPLE_LIST_H

然后是实现:


#include"native-linklist.h"

JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_init(JNIEnv *env,jobject thiz){
    startNode=new Node();
    endNode=new Node();
    nextNode=new Node();
    nextNode->next=startNode;
    startNode->next=endNode;
    startNode->pre= nullptr;
    endNode->pre=startNode;
    endNode->next= nullptr;
}
JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_add(JNIEnv *env,jobject thiz,jint jst,jstring obj){
    count++;
    int key=jst;
    const char *value=env->GetStringUTFChars(obj,JNI_FALSE);
    if(startNode->getvalue()== nullptr){
        startNode->set(key,value);
    }else{
        Node *elem=new Node(key,value);
        elem->next=endNode;
        elem->pre=endNode->pre;
        endNode->pre->next=elem;
        endNode->pre=elem;
    }
}
JNIEXPORT jint JNICALL Java_com_xuye_xy_socket_jni_LinkList_size(JNIEnv *env,jobject thiz){
    return count;
}
JNIEXPORT jobject JNICALL Java_com_xuye_xy_socket_jni_LinkList_next(JNIEnv *env,jobject thiz){
    if(nextNode!= nullptr&&nextNode->next!= nullptr&&nextNode->next->getvalue()!= nullptr){
        const char *value=nextNode->next->getvalue();
        int key=nextNode->next->getkey();
        jobject nodeobj=newNode(env,key,value);
        nextNode->next=nextNode->next->next;//下一个
        return nodeobj;
    }
    return nullptr;
}

JNIEXPORT void JNICALL Java_com_xuye_xy_socket_jni_LinkList_prenext(JNIEnv *env,jobject obj){
    nextNode=new Node();
    nextNode->next=startNode;
}

JNIEXPORT jboolean JNICALL Java_com_xuye_xy_socket_jni_LinkList_hasnext(JNIEnv *env,jobject thiz){
    if(nextNode!= nullptr&&nextNode->next!= nullptr&&nextNode->next->getvalue()!= nullptr){
        return true;
    }
    return false;
}


JNIEXPORT jstring JNICALL Java_com_xuye_xy_socket_jni_LinkList_get(JNIEnv *env,jobject thiz,jint key){
    Node *temp=new Node();
    temp->next=startNode;
    while (temp->next!= nullptr){
        if(temp->next->getkey()==key)
            return env->NewStringUTF(temp->next->getvalue());
        temp=temp->next;
    }
    return nullptr;
}

jobject newNode(JNIEnv *env,int key, const char *value){
    jclass nodeclass=env->FindClass("com/xuye/xy/socket/java/Node");//获取到Node类
    jmethodID nodeinit=env->GetMethodID(nodeclass,"<init>","()V");//获取到Node实例化方法
    jmethodID   nodesetkey=env->GetMethodID(nodeclass,"setKey","(I)V");//获取到设置Key的方法
    jmethodID nodesetvalue=env->GetMethodID(nodeclass,"setValue","(Ljava/lang/String;)V");//获取到设置value的方法
    jobject nodeobj=env->NewObject(nodeclass,nodeinit);//创建一个新的Node
    env->CallVoidMethod(nodeobj,nodesetkey,key);//设置key
    jstring valuestr=env->NewStringUTF(value);
    env->CallVoidMethod(nodeobj,nodesetvalue,valuestr);//设置value
    return nodeobj;
}

MainActivity的调用:


    private LinkList list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        list=new LinkList();
        for(int i=0;i<1000;i++){
            list.add(i,new String("第"+i+"个"));
        }
        list.prenext();
        StringBuilder builder=new StringBuilder();
        while (list.hasnext()){
            Node node=list.next();
            node.log();
        }
        tv.setText(list.get(5));
    }

执行后打印结果如下:
这里写图片描述
在这里对于基础学习有2个地方需要注意:
第一个是在构建对应的.h文件时,可以利用javah命令生成和Java对应的.h文件;
第二个是在需要调用Java对象或者方法的时候,可以利用javap命令获取到签名,在C中进行调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值