03_jni_helloworld_完成
通过ndk-build编译C的代码.cd /d就是直接进到我的目录里面.

打开ANDROID-MK.HTML

Introduction:
This document describes the syntax of Android.mk build file written to describe your C and C++ source files to the Android NDK. To understand what follows, it is assumed that you have read the OVERVIEW file that explains their role and usage.
Overview:
An Android.mk file is written to describe your sources to the build system. More specifically:
The file is really a tiny GNU Makefile fragment that will be parsed one or more times by the build system. As such, you should try to minimize the variables you declare there and do not assume that anything is not defined during parsing.
Simple example:
---------- cut here ------------------
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)
---------- cut here ------------------
mk是linux下的makefile文件.makefile就是向编译系统描述我要打包、生成、编译的资源在什么地方. 实际上咱们编译java的时候也有这样的流程,只不过有IDE集成开发环境帮咱们都做好了. $(call my-dir) $符号调用指令call my-dir 通过这个命令获取当前目录
$(CLEAR_VARS) 咱们把makefile在编译的时候系统会把它解析.解析之后执行相关的指令.执行完指令了所有的这个makefile执行完之后的结果都会存在一个公共的地方.CLEAR_VARS把上一次编译生成的信息给它清空.把这些变量都
清空.但是call my-dir这个变量这里面的内容是不会被清除掉的. .so是linux下的动态链接库.windows上的动态链接库叫做.dll..dll随便翻一番windows的目录都能找到这个东西:windows的动态链接库.在运行的时候它会把它加载进来.
好,写完Android.mk之后再次运行ndk-build
#makefile 作用就是向编译系统描述 我要编译的文件在什么位置 要生成的文件叫什么名字, 是什么类型
#上面先获取一下当前的路径 在当前路径下去找hello-jni.c
LOCAL_PATH := $(call my-dir)
#清除上次编译的信息
include $(CLEAR_VARS)
#在这里指定最后生成的文件的名字
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c#现在咱们要编译的是hello.c
#要编译的C的代码的文件名
include $(BUILD_SHARED_LIBRARY)
#要生成的是一个动态链接库
所以要给hello.c引入头文件jni.h
#include <stdlib.h>
#include <stdio.h>
#include <jni.h>

已经编译完了,生成一个libhello.so.

C的函数已经编译生成了一个.so文件.下一步就要想办法调用它一下.
把libhello.so加载进来之后才可以调用它.
public void jniHello(View v){//Java不实现,只声明.
System.loadLibrary("hello");




#include <stdlib.h>
#include <stdio.h>
#include <jni.h>
/*int main(int argc, char **argv) {//main是程序的入口.
//但是今天java才是程序的入口,只不过是把一个方法通过C来实现.所以在C这边只需要写一个函数.
//那这个函数是对我native方法的具体实现.
//今天程序的入口是咱们的安卓应用.所以不能用main.
}
*/ /*char* helloInC(){//人家java要的是String,你的是char *;你的helloInC怎么对java那边的helloInC().
//char *和String还是有点区别的.
//java的String一定是丢在堆内存里面的,C的char *不一定丢在堆内存里面,有可能在栈里面.
//所以实际上char *和String不是一种类型.所以这么写也不靠谱. }
*/
//本地函数命名规则 Java_包名_native函数所在类的类名_native方法名
//第二个参数jobject thiz 就是调用当前native方法的java对象.
//第一个参数 JNIEnv* JNIEnv是结构体 JNINativeInterface这个结构体的一级指针
//env又是JNIEnv的一级指针 那么env就是JNINativeInterface的二级指针
//结构体JNINativeInterface定义了大量的函数指针 这些函数指针在JNI开发中十分常用.
//这些功能实际上都是通过JNINativeInterface这里面定义的这些函数指针来实现的.实际上就类似于一个函数表.这里面就可以调用到JNI开发常用的函数,通过函数指针来进行调用的.
//调用函数的第一种方法:(**env).func
//第二种方式:(*env)->
//jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
// jobject thiz )
//jString是Java的String类型在C里面具体的表示的方式.
jstring Java_com_itheima_hello_MainActivity_helloInC( JNIEnv* env,
jobject thiz ){
//就得调用(*env)里面的函数指针实现相关的功能
//有没有哪一个函数指针它的返回值是一个jstring.
// jstring (*NewStringUTF)(JNIEnv*, const char*);
char* str ="hello from c!!!!!";//C的环境只能定义char*
//得把char*转化成一个jstring类型才能返回.这些功能实际上都在这个JNIEnv所指向的这个JNINativeInterface里面.
//通过newStringUTF 方法把C的字符串 转换成java的jstring类型.
return (*env)->NewStringUTF(env,str);//(*env)->转化成一级指针调用 }
package com.itheima.hello; import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Toast; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} public void jniHello(View v){//Java不实现,只声明.
System.loadLibrary("hello");
//通过这个声明去调到C的方法.所以在Java这边去搞一个函数的声明.
//调用本地方法 并且把返回的值通过吐司显示出来
Toast.makeText(this, helloInC(), Toast.LENGTH_SHORT).show();//拿到C返回的字符串.
}
//public abstract String helloInC();//不能用抽象,abstract还不行.
//用关键字native声明一个放在C这边的函数 通过native关键字声明了一个本地方法.
//本地方法不用实现,需要用jni调用C的代码来实现
public native String helloInC();
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="jniHello"
android:text="调用C的函数" /> </RelativeLayout>
#makefile 作用就是向编译系统描述 我要编译的文件在什么位置 要生成的文件叫什么名字, 是什么类型
#上面先获取一下当前的路径 在当前路径下去找hello-jni.c
LOCAL_PATH := $(call my-dir)
#清除上次编译的信息
include $(CLEAR_VARS)
#在这里指定最后生成的文件的名字
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c#现在咱们要编译的是hello.c
#要编译的C的代码的文件名
include $(BUILD_SHARED_LIBRARY)
#要生成的是一个动态链接库
03_jni_helloworld_完成的更多相关文章
随机推荐
- 字符串--P1308 统计单词数
题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...
- Linux---文件目录管理
1. Linux文件目录架构 Linux的目录结构与win的目录有很大不同,首先,没有盘符的概念:然后Linux使用斜杠/标识目录,Linux首先建立一个根目录,然后将其他文件系统挂载到这个目录下. ...
- 配置JSTL
1.去到官网下载好 4个包 http://tomcat.apache.org/download-taglibs.cgi 2.然后拷贝到 lib目录下 3.导入进去 后面的 C 代替了导入包的名字 4 ...
- CCF201612-1 中间数 java(100分)
试题编号: 201612-1 试题名称: 中间数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 在一个整数序列a1, a2, …, an中,如果存在某个数,大于它的整数数量等 ...
- python爬虫27 | 当Python遇到MongoDB的时候,存储av女优的数据变得如此顺滑爽~
上次 我们知道了怎么操作 MySQL 数据库 python爬虫26 | 把数据爬取下来之后就存储到你的MySQL数据库. MySQL 有些年头了 开源又成熟又牛逼 所以现在很多企业都在使用 MySQL ...
- Pygame游戏开发入门(1)-开发框架
pygame库的安装 pip install pygame pygame最小开发框架 #Pygame Hello World Game import pygame,sys #引入pygame和sys( ...
- 浅谈对java-GC的理解
前段时间,一个线上项目忽然很卡,通过监控,发现内存很高,果不其然在几个小时后,OOM.虽说有人很快处理好了.但我还是想站在我的角度,对这件事发表一下自己的观点. 内存溢出,多发生在项目上线后,而且在系 ...
- SRAM的简单概念
CY7C138 版权声明:本文为博主原创文章,未经博主允许不得转载.
- maven profile多环境自动切换配置,配置分离,排除文件
痛点: 在java开发的过程中,我们经常要面对各种各样的环境,比如开发环境,测试环境,正式环境,而这些环境对项目的需求也不相同. 在此之前,我们往往需要手动去修改相对应的配置文件然后打成war,才能部 ...
- 【Codeforces 279C】Ladder
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 设pre[i]表示i往前一直递增能递增多远 设aft[i]表示i往后一直递增能递增多远 如果aft[l]+pre[r]>=(r-l+1) ...