JNI(Java Native Interface)_01
習慣
1、技術是什麼?
2、爲什麼要使用這個技術?
3、怎麼使用?
4、實際怎麼應用?
jni 是什麼
* jni (java native interface)
* 兩張不同編程語言之間通訊
java:
特點:一次編寫,到處運行
java源代碼--->.class--->JVM--->os
c/c++
源代碼--->os(01)
java(中國人)---JNI---c/c++(日本人)
jni:兩種不同編程語言之間的通訊
爲什麼要使用jni
*需求(錢):JNI是各種編程語言之間的橋樑
*物聯網:劉德華喫綠色豬
*特殊設備(機頂盒、人臉識別):
*高性能(c比java快)
*老闆要求(支付寶客戶端):java的反編譯容易,c不容易
怎麼使用jni
*java基礎
*c、c++基礎
*jni開發
老師演示:
*使用c語言中的system語句打開java程序:system("java Hello");
*使用c語言打開本地畫板
*eclipse也是sun公司用java語言編寫的,然而打開eclipse.exe的原理其實就是c語言調用java程序jar
java 八種基本數據類型
* byte 1byte
* short 2
* int 4
* long 8
* float 4
* double 8
* char 2
* boolean 1
c 數據類型
c的基本數據類型
*char 1byte
*int 4
*float 4
*double 8
*long 4
*short 2
*void
輸出函數
%d -int
輸入:
scanf
指針就是地址,地址就是指針
安裝cheat Engine,監控軟件在內存中的任何一個地址
遊戲作弊:掃雷
案例:炸彈倒計時.c
*號的用法
* 1, 連個數相乘 a * b (int a, int b)
* 2, 聲明指針變量 數據類型* 變量名;
* 3, 取指針(地址)上的值 *變量名
指針
1、指針的基本語法
int age = 5;//1、先爲age分配內存,2、賦值爲5
int* page = &age;//page是一個指針變量,該變量可以指向一個int數據的地址
printf("page=%#x,age地址:%#x\n",page,&age);
printf("*page=%d,age地址:%d\n",*page,age);
*號的用法:
1、兩個數的相乘
2、聲明指針變量 數據類型* 變量名;
3、取指針(地址上)的值
* & 互爲逆運算
2、指針的常見錯誤
什麼數據類型的指針變量,只能指向該數據的地址
int a = 3;
float b = 4.4;
int* pa = &a;
int* pb = &b;//float* pb = &b;
//以上的操作導致下面輸出*pb=0.0
printf("*pa=%d,*pb=%.1f",*pa,*pb);
以上結論就是:什麼類型的數據地址就存放在什麼類型的指針變量
//int *p;//指針使用之前要給它賦值,如果不賦值,就是一個野指針。
int* p = 0;//所以要這樣初始化--->指針指向了空
或者
int* p = null;//null的值其實就是0
指針變量就是存放數據的地址,數據的地址(0x1122ddAA):四位的十六進制數表示:4個字節
所以說所有的數據類型的指針變量長度都是4字節,長度4
printf("*p的長度:%d\n",sizeof(p));
java沒有指針,但一切對象皆指針。
c的邏輯類型
true 非0 FALSE 0
兩個數交換
c的實例
void change(int a ,int b){
int c = a;
a = b;
b = c;
}
main(){
int a = 3;
int b = 5;
change(a,b);
printf("%d,%d",a,b);
}
輸出3,5 爲什麼?畫內存圖:棧內存
void change2(int* pa ,int* pb){
int c = *pa;
*pa = *pb;
*pb = c;
}
main(){
int a = 3;
int b = 5;
change(&a,&b);
printf("%d,%d",a,b);
}
輸出:5,3
java的實例(畫內存圖)
public class Hello
{
static void change2(Integer a,Integer b)
{
Integer c = a;
a = b;
b = c;
}
static void change(int a, int b){
int c = a;
a = b;
b = c;
}
static void change(MyPoint point){
int c = point.x;
point.x = point.y;
point.y = c;
}
public static void main(String[] args)
{
//int a1 = 3;
//int b1 = 5;
//change(a1,b1);
//System.out.println("a1="+a1 + ",b1=" + b1);
//change2(a1,b1);
MyPoint my = new MyPoint();
my.x = 3;
my.y = 5;
change(my);
System.out.println("x="+ my.x + ",y=" + my.y);
}
}
class MyPoint
{
int x;
int y ;
}
jni實際開發經驗
利用指針返回多值
方法不能修改實際參數的值:即我們修改不了一個變量所對應的地址值
動態申請內存:int *p1 = malloc(4);//和java中new一個對象很像,申請到的地址,在堆內存
通過free釋放空間
學會畫C與Java的內存空間圖,有助於理解兩語言間的底層運行
01.calljava.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
main() // public static void main(String[] arg)
{
printf("c Hello world !\n"); // System.out.print(); \n表示換行
system("mspaint");
system("pause");// system函數 直接調用dos命令
}
02.c基本數據類型.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
//char
// int float double signed, unsigned, long, short and void
main() // public static void main(String[] arg)
{
signed char i = 156;// -128 ~ 127
printf("i=%d\n",i);
printf("char length:%d\n",sizeof(char));
printf("int length:%d\n",sizeof(int));
printf("float length:%d\n",sizeof(float));
printf("double length:%d\n",sizeof(double));
printf("long long length:%d\n",sizeof(long long));
printf("short length:%d\n",sizeof(short));
printf("Hello world !\n"); // System.out.print(); \n表示換行
system("pause");// system函數 直接調用dos命令
}
//i=-100
//char length:1
//int length:4
//float length:4
//double length:8
//long long length:8
//short length:2
//Hello world !
//請按任意鍵繼續. . .
03.c_函數出棧.c
#include <stdio.h>
#include <stdlib.h>
void changea(int a)
{
a = 100;
}
void changeb(int* pa)
{
*pa = 100;
}
/*
方法不能修改實際參數的值
*/
void change(int* ptemp)
{
int a = 3;
int* pa = &a;
ptemp = pa;
printf("&a=%#x\n",pa);
}
void changec(int** ptemp)
{
//int a = 3;
int *p1 = malloc(4);// malloc(4); 申請到的地址 在堆內存 通過free釋放空間
*p1 = 3;
int* pa = p1;
*ptemp = pa;
printf("&a=%#x\n",pa);
free(p1);
}
main()
{
/*
changeb(&num);
printf("num=%d\n",num);
*/
// int num = 5;
int* pnum = 0;
// printf("%d\n",*pnum);
changec(&pnum);
printf("<><><><><><>\n");
printf("<><><><><><>\n");
printf("*pnum=%d,pnum=%#x\n",*pnum,pnum);
system("pause");
}
//&a=0x850f58
//<><><><><><>
//<><><><><><>
//*pnum=8720320,pnum=0x850f58
//請按任意鍵繼續. . .
04.c輸出.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
/*
%d - int
%ld – long int
%c - char
%f - float
%u – 無符號數
%hd – 短整型
%lf – double
%x – 十六進制輸出 int 或者long int 或者short int
%o - 八進制輸出
%s – 字符串
*/
main() // public static void main(String[] arg)
{
char str[] = "andy";///{'a','n','d','y','\0'};
int d = 33;
float f = 23.3;
printf("d=%d,f=%.1f,str=%s\n",d,f,str);
printf("Hello world !\n"); // System.out.print(); \n表示換行
system("pause");// system函數 直接調用dos命令
}
//d=33,f=23.3,str=andy
//Hello world !
//請按任意鍵繼續...
05.c輸入.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
/*
%d - int
%ld – long int
%c - char
%f - float
%u – 無符號數
%hd – 短整型
%lf – double
%x – 十六進制輸出 int 或者long int 或者short int
%o - 八進制輸出
%s – 字符串
*/
main() // public static void main(String[] arg)
{
printf("學生輸入信息:\n");
int sid;
int age;
char name[10];
printf("學號:");
scanf("%d",&sid);
printf("年齡:");
scanf("%d",&age);
printf("名字:");
scanf("%s",&name);
printf("學號:%d,年齡:%d,名字:%s\n",sid,age,name);
system("pause");// system函數 直接調用dos命令
}
//學生輸入信息:
//學號:1
//年齡:2
//名字:andy
//學號:1,年齡:2,名字:andy
//請按任意鍵繼續...
05_炸彈倒計時.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
main() // public static void main(String[] arg)
{
printf("炸彈離爆炸剩餘時間\n"); // System.out.print(); \n表示換行
int time = 100;
printf("time的地址:%#x\n",&time);
for (; time > 0 ; time--)
{
printf("爆炸倒計時:%d\n",time);
sleep(2000);
}
system("pause");// system函數 直接調用dos命令
}
06_指針基本語法.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
main() // public static void main(String[] arg)
{
int age = 5;// 1,先爲age分配內存, 2,賦值爲5 int age; age = 5;
int* page = &age;// page是個指針變量,該變量可以指向一個int數據的地址
// * & 互爲逆運算
printf("page=%#x,age地址:%#x\n",page,&age);
printf("*page=%d,age值:%d\n",*page,age);
system("pause");// system函數 直接調用dos命令
}
//page=0x22ff44,age地址:0x22ff44
//*page=5,age值:5
//請按任意鍵繼續。。。
07_指針的常見錯誤.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
main() // public static void main(String[] arg)
{
// 什麼數據類型的指針變量 只能指向該數據的地址
//
int a = 3;
float b = 4.4;
int* p = NULL;//指針使用之前要賦值,如果不賦值 野指針
char* c = NULL;
// 指針變量 存放的就是數據的地址 ,數據的地址(0x1122ddAA) 4個字節 ,所有類型的指針變量,長度都是4
if (p == NULL){
printf("p沒有指向一個數據的地址");
}
printf("p=%d,c=%d\n",sizeof(p),sizeof(c));
int* pa = &a;// pa 指向 int數據的地址
float* pb = &b;
printf("*pa=%d,*pb=%.1f\n",*pa,*pb);
printf("Hello world !\n"); // System.out.print(); \n表示換行
system("pause");// system函數 直接調用dos命令
}
08_交換兩個數據.c
#include <stdio.h> // java 中 import java.util.ArrayList
#include <stdlib.h> // stdio 輸入輸出頭文件 stdlib 標準函數庫
void change(int a, int b)
{
int c = a;
a = b;
b = c;
}
void change2(int* pa,int* pb)
{
int c = *pa;
*pa = *pb;
*pb = c;
}
main() // public static void main(String[] arg)
{
int n1 = 2;
int n2 = 3;
change(n1,n2);
printf("n1=%d,n2=%d\n",n1,n2);
change2(&n1,&n2);
printf("n1=%d,n2=%d\n",n1,n2);
system("pause");// system函數 直接調用dos命令
}
//n1=2,n2=3
//n1=3,n2=2
//請按任意鍵繼續. . .
09_指針返回多值.c
#include <stdio.h>
#include <stdlib.h>
void getxy(int* px,int* py)
{
*px = 200;
*py = 250;
}
main()
{
int x ,y ;
getxy(&x,&y);
printf("x=%d,y=%d\n",x,y);
system("pause");
}
//x=200,y=250
//請按任意鍵繼續。。。
10_多級指針.c
#include <stdio.h>
#include <stdlib.h>
main()
{
int i = 5;
int* p1 = &i;
int** p2 = &p1;
// int*** p ; ***p int類型;
printf("i=%d,p1=%d,p2=%d\n",i,*p1,**p2);
system("pause");
}
//i=5,p1=5,p2=5
//請按任意鍵繼續。。。
11_數組.c
#include <stdio.h>
#include <stdlib.h>
void setdatas(int ar[],int len)
{
int i = 0;
for (; i < len; i++)
{
ar[i] = i + 1;
}
}
void printdatas(int ar[],int len)// 形式參數 int ar[], int *ar
{
printf("ar size:%d\n",sizeof(ar));
// int len = sizeof(datas)/sizeof(datas[0]);
int i = 0;
for (; i < len; i++)
{
printf("ar[%d]=%d,&ar[%d]=%#x\n",i,ar[i],i,&ar[i]);
}
}
void printp(int* ar,int len)
{
printf("ar size:%d\n",sizeof(ar));//輸出4字節,這是地址的長度
// int len = sizeof(datas)/sizeof(datas[0]);
int i = 0;
for (; i < len; i++)// *(ar+i) 等價於 ar[i] 對指針變量加1 以指針類型爲單位 如: int* 1 4byte short* 1 2byte
{
printf("ar[%d]=%d,&ar[%d]=%#x\n",i,*(ar + i),i,&ar[i]);
}
}
main()
{
//datas 表示數組第一個元素地址的常量
int datas[5]; // int datas[] = new int[5];
setdatas(datas,5);
printdatas(datas,5);
datas[5] = 33;
printp(datas,6);
printf("datas length:%d\n",sizeof(datas)/sizeof(datas[0]));
system("pause");
}
//ar size:4
//ar[0]=1,&ar[0]=0x22ff20
//ar[1]=2,&ar[1]=0x22ff24
//ar[2]=3,&ar[2]=0x22ff28
//ar[3]=4,&ar[3]=0x22ff2c
//ar[4]=5,&ar[4]=0x22ff30
//ar size:4
//ar[0]=1,&ar[0]=0x22ff20
//ar[1]=2,&ar[1]=0x22ff24
//ar[2]=3,&ar[2]=0x22ff28
//ar[3]=4,&ar[3]=0x22ff2c
//ar[4]=5,&ar[4]=0x22ff30
//ar[5]=33,&ar[5]=0x22ff34
//datas length:5
//請按任意鍵繼續. . .
12_short數組.c
#include <stdio.h>
#include <stdlib.h>
void initdatas(short *a)
{
printf("a size:%d\n",sizeof(a));
}
main()
{
/*
指針變量加減1的單位 1 看指針的數據類型 如 int* 1 4byte
僅限於數組
*/
short datas[5]; //datas 等價於 &datas[0]
initdatas(datas);
printf("datas length:%d\n",sizeof(datas));//10
short* p = datas;// short* p = &datas[0] ;
printf("datas length:%d\n",sizeof(p));//4
//爲什麼他們有這種區別,因爲當他們在實參中就有這種區別,但是如果在形參中就沒有任何區別
int i = 0;
for (; i < 5; i++)
{
printf("&p[%d]=%#x,p[%d]=%d\n",i,p + i,i,*(p++));// (p + i) 等價於 &p[i]
}
system("pause");
}
//a size:4
//datas length:10
//datas length:4
//&p[0]=0x22ff32,p[0]=212
//&p[1]=0x22ff36,p[1]=0
//&p[2]=0x22ff3a,p[2]=8752
//&p[3]=0x22ff3e,p[3]=80
//&p[4]=0x22ff42,p[4]=53
//請按任意鍵繼續. . .
13_指針與字符串.c
#include <stdio.h>
#include <stdlib.h>
main()
{
char str[] = {'a','b'};//"hello\0world";// 字符串有結束符\0
printf("str[]length:%d, strlength = %d\n",sizeof(str),strlen(str));
system("pause");
}
//str[]length:2, strlength = 5
//請按任意鍵繼續. . .
14_學號管理系統.c
#include <stdio.h>
#include <stdlib.h>
void printstus(int* s,int len)
{
int i = 0;
for (; i < len ; i++)
{
printf("第%d個學生的學號爲:%d\n",i + 1,s[i]);
}
//printf("");
}
main()
{
printf("歡迎使用學生學籍管理系統\n");
int number;//學生的數量
printf("請輸入錄入學生的數量:");
scanf("%d",&number);
if (number < 1)
{
printf("請按套路出牌\n");
system("pause");
return;
}
//輸入合法的數字
int* stus = malloc(number * sizeof(int)); //動態申請內存(在堆)
// int stus[number];
int i = 0;
for (; i < number;i++)
{
printf("請輸入第%d個學生學號:",(i + 1));
scanf("%d",stus+i);
}
int type ;
printf("%d個學號已經輸入完畢,查看學生請輸入1,追加輸入學生請輸入2\n 請輸入:",number);
scanf("%d",&type);
if (type == 1)
{
printstus(stus,number);
} else if (type != 2){
printf("請按套路出牌\n");
system("pause");
return;
} else { // thype 2
int numapp;//學生的數量
printf("請輸入錄入學生的數量:");
scanf("%d",&numapp);
stus = realloc(stus,(number + numapp) * sizeof(int)); //追加內存,在原理的內存基礎上追加內存個數
for (; i < number + numapp;i++)
{
printf("請輸入第%d個學生學號:",(i + 1));
scanf("%d",stus+i);
}
printstus(stus,number + numapp);
}
system("pause");
}
//歡迎使用學生學籍管理系統
//請輸入錄入學生的數量:3
//請輸入第1個學生學號:110
//請輸入第2個學生學號:120
//請輸入第3個學生學號:130
//3個學號已經輸入完畢,查看學生請輸入1,追加輸入學生請輸入2
// 請輸入:2
//請輸入錄入學生的數量:2
//請輸入第4個學生學號:140
//請輸入第5個學生學號:150
//第1個學生的學號爲:110
//第2個學生的學號爲:120
//第3個學生的學號爲:130
//第4個學生的學號爲:140
//第5個學生的學號爲:150
//請按任意鍵繼續. . .
15_結構體.c
#include <stdio.h>
#include <stdlib.h>
int add(int a, int b)
{
return a + b;
}
int mul(int a, int b)
{
return a * b;
}
struct Student
{
int id; // 4
char sex;// 1
short age;// 2
char *name;//4
int (*op)(int a, int b);
};
// c 結構體 只能屬性 不能聲明方法
typedef struct Student STU;
typedef int haha;
main()
{
STU s1 = {101,'m',22,"andy",add};
s1.id = 1011;
STU* ps = &s1;
printf("ps size=%d\n",sizeof(s1));
printf("stu.id=%d\n",ps->id);//(*ps).id
int res = s1.op(4,6);
printf("res=%d\n",res);
system("pause");
}
//ps size=16
//stu.id=1011
//res=10
//請按任意鍵繼續. . .
16_函數指針.c
#include <stdio.h>
#include <stdlib.h>
int add(int a, int b)
{
return a + b;
}
int mul(int a, int b)
{
return a * b;
}
main()
{
int (*op)(int a, int b);// op函數指針變量
op = mul;
int res = (*op)(3,5);
printf("res=%d\n",res);
system("pause");
}
//res=15
//請按任意鍵繼續. . .
17_聯合體.c
#include <stdio.h>
#include <stdlib.h>
union Data
{
char c;
int num;
short s;
};
main()
{
//公共體(聯合體) 以成員的最大數據類型,作爲該聯合體的長度
union Data d;
printf("%d\n",sizeof(d));
d.num = 0x11221361;
printf("%hd\n",d.s);
printf("%d\n",d.num);
printf("%c\n",d.c);
system("pause");
}
//4
//4961
//287445857
//a
//請按任意鍵繼續. . .
18_枚舉.c
#include <stdio.h>
#include <stdlib.h>
enum Color
{
red=1,black,green,yellow,cyan,blue
};
main()
{
enum Color c;
c = yellow;
printf("%d\n",c);
system("pause");
}
//4
//請按任意鍵繼續. . .
19_宏定義.c
#include <stdio.h>
#include <stdlib.h>
#define null 0
#define mul(a,b) ((a) * (b))
main()
{
printf("%d\n",mul(3 + 2,2 + 4) * 3);// add(3,4) a + b > 3 + 2 * 2 + 4 * 3
//printf("str[]length:%d, strlength = %d\n",sizeof(str),strlen(str));
system("pause");
}
//90
//請按任意鍵繼續. . .
20_靜態變量.c
#include <stdio.h>
#include <stdlib.h>
void add()
{
static int i = 5;
i++;
printf("i=%d\n",i);
}
main()
{
add();
add();
system("pause");
}
//i=6
//i=7
//請按任意鍵繼續. . .
資料下載