什麼是JNIhtml
JNI(Java Native Interface) java本地開發接口
JNI 是一個協議, 有了這個協議可使Java代碼和C/C++代碼相互調用.java
爲何用JNIandroid
1、擴展JVM功能,訪問驅動,操做硬件(物聯網、智能家居、
車載電腦)
2、效率上c/c++語言效率更高數學運算,實時渲染的遊戲上,音
視頻處理
3、 java反編譯比c語言容易, 經過JNI加強代碼安全性(加密算法放到C實現)c++
4、代碼移植,複用已經存在的c代碼(opencv,ffmpeg…)程序員
怎麼用JNI算法
1.C/C++語言
2.掌握java jni流程
3.NDK (native develop kits )shell
開發環境介紹編程
windows下用輕量級 dev-c++windows
C語言基本數據類型數組
Java 八大基本數據類型 C基本數據類型
boolean
byte
char char
int int
float float
double double
long long
short short
C沒有boolean byte
signed unsigned 有符號無符號修飾符只能修飾整形變量
signed 有符號最高位符號位能夠表示負數
unsigned 無符號最高位仍然是數值位不能夠表示負數
輸入輸出函數
輸出函數
printf(「要輸出的內容+佔位符」,…….)
經常使用佔位符
%d - int
%ld – long int
%lld - long long
%hd – 短整型
%c - char
%f - float
%lf – double
%u – 無符號數
%x – 十六進制輸出 int 或者long int 或者short int
%o - 八進制輸出
%s – 字符串
輸入函數 Scanf
Int len;
Scanf(「%d」,&len); &取地址符號
什麼是指針
int main(void) { int * p; //p 是變量的名字, int * 是一個類型 //這個變量存放的是int類型變量的地址。 int i =3; p=&i; system(「pause」); return 0; }
指針常見錯誤
指針變量聲明後未賦值直接用
聲明的指針類型和指向的類型要一致
指針和指針變量的關係
指針就是地址,地址就是指針
地址就是內存單元的編號
指針變量是存放地址的變量
指針和指針變量是兩個不一樣的概念
可是要注意:一般咱們敘述時會把指針變量簡稱爲指針,實際它們含義並不同
爲何使用指針
直接訪問硬件 (opengl 顯卡繪圖)
快速傳遞數據(指針表示地址)
返回一個以上的值(返回一個數組或者結構體的指針)
表示複雜的數據結構(結構體)
方便處理字符串
*號的三種含義
*號的含義
數學運算符: 3 * 5
定義指針變量: int * p;
指針運算符(取值): *p (取p的內容(地址)在內存中的值)
指針練習互換兩個數字
swap(int* i, int* j) { // 引用傳遞 int temp = *i; *i = *j; *j = temp; } main() int i = 89; int j = 10; swap(&i, &j); printf("i=%d\n", i); printf("j=%d\n", j); system("pause"); }
指針練習函數返回一個以上的值
change(int* a, int* b) { *a = 1; *b = 2; } main() { int a = 3, b = 5; change(&a, &b); printf(「a=%d, b=%d\n」, a, b); system(「pause」); }
指針和數組的關係
數組名
int a[5]; // a是數組名,5是數組的大小,元素個數
數組名稱是個指針常量,它存放的是數組中第一個元素的地址
int a[5];
&a[0] 等價於 &a
下標和指針的關係
int a[5];
a[i] 等價於 *(a + i) // 這裏i的範圍是0~4(數組長度 -1)
指針的長度
無論什麼類型的指針都是4個字節.(64位系統8字節)
C語言爲了方便指針運算, 定義各類基本類型的指針, 每種類型的指針運算時所偏移量的值是根據類型的長度決定的.
多級指針
int i = 10; int* p1 = &i; // 一級指針 int** p2 = &p1; // 二級指針 int*** p3 = &p2; // 三級指針 int**** p4 = &p3; // 四級指針 ****p4 = 99; // 修改變量i的值爲99;
主函數獲取子函數變量地址
void function(int** p){ int i = 4; *p = &i; printf("子函數打印i的地址爲%#x\n", &i); } main(){ int* mainp; function(&mainp); printf("主函數打印i的地址爲%#x\n", mainp); printf("i的值爲%d\n", *mainp); system("pause"); }
靜態內存和動態內存
靜態內存是系統是程序編譯執行後系統自動分配,由系統自動釋放, 靜態內存是棧分配的.
動態內存是開發者手動分配的, 是堆分配的.
棧內存
* 系統自動分配
* 系統自動銷燬
* 連續的內存區域
* 向低地址擴展
* 大小固定
* 棧上分配的內存稱爲靜態內存
堆內存
* 程序員手動分配
* java:new * c:malloc
* 空間不連續
* 大小取決於系統的虛擬內存
* C:程序員手動回收free
* java:自動回收
* 堆上分配的內存稱爲動態內存
申請堆內存
malloc(memory allocate) 函數
malloc 申請一塊堆內存
free(地址); 回收內存
回收malloc 申請的堆內存
realloc re- allocate
從新申請一塊堆內存
結構體
struct Student { int age; float score; char sex; }; main() { struct Student stu = {18, 88.5, 'M'}; }
使用結構體變量
struct Student stu = {80,55.5,'F'}; struct Student stu2; stu2.age = 10; stu2.score = 88.8f; stu2.sex= ‘M'; printf("%d %f %c\n", st.age, st.score, st.sex); // 結構體指針 struct Student * pStu; pStu = &stu; pStu->age 在計算機內部會被轉換爲 (* pStu).age
pStu ->age的含義: pStu所指向的結構體變量中的age這個成員
函數的指針
1.定義int (*pf)(int x, int y);
2.賦值 pf = add;
3.引用 pf(3,5);
4.結構體中不能定義函數,只能聲明函數指針
Union 聯合體
struct Date { int year; int month; int day; }; union Mix { long i; int k; char ii; }; main() { printf("date:%d\n",sizeof(struct Date)); printf("mix:%d\n",sizeof(union Mix)); system("pause"); }
枚舉
enum WeekDay { Monday=0,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday }; main() { enum WeekDay day = Sunday; printf("%d\n",day); system("pause"); }
typedef
聲明自定義數據類型,配合各類原有數據類型來達到簡化編程的目的的類型定義關鍵字。
#include <stdio.h> #include <stdlib.h> typedef int i; typedef long l; main() { i m = 10; l n = 123123123; printf("%d\n", m); printf("%ld\n", n); system("pause"); }
JNI 協議
NDK HelloWorld
1.建立一個android工程
2.java代碼中寫聲明native方法
3.建立jni目錄,編寫c代碼,方法名字要對應
4.編寫Android.mk文件
5.NDK編譯生成動態連接庫
6.java代碼load動態庫.調用native代碼
javah 生成頭文件
注意: 不一樣版本的JDK操做方式不一樣.
命令: javah <包名+類名>
JDK1.6使用方式
在工程的bin/classes目錄下, 執行javah命令.
JDK1.7使用方式
在工程的src目錄下, 執行javah命令.
NDK 簡便開發流程
1. 關聯NDK: Window -> Preferences -> Android -> NDK
2. 建立Android工程, 聲明native方法.
3. 設置函數庫名字: 右鍵工程 -> Android Tools -> App Native support
4. 使用javah生成.h的頭文件, 並把.h文件拷貝到工程下jni文件夾中.
5. c代碼提示: 右鍵工程 -> Properties -> C/C++ General -> Path and Symbols // Includes -> Add -> File system 選中如下路徑.latforms\android-18\arch-arm\usr\include
6. 把後綴名.cpp改爲.c, 實現native方法.
7. java代碼中加載動態庫, 調用native方法.
java 與 c之間的數據傳遞
public native int add(int x, int y);
public native String sayHelloInC(String s);
public native int[] arrElementsIncrease(int[] intArray);
在c代碼中使用logcat
Android.mk文件增長如下內容
LOCAL_LDLIBS += -llog
C代碼中增長如下內容
#include <android/log.h #define LOG_TAG "System.out" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) C代碼中使用logcat, 例: LOGI("info\n"); LOGD("debug\n");
C語言調用java方法
C調用java空方法
public void helloFromJava(){
}
C調用java中的帶兩個int參數的方法
public int add(int x,int y) {
}
C調用java中參數爲string的方法
public void printString(String s){
}
JNI 方法簽名
簽名類型 Java類型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L全類名; 引用類型
[類型數組
C語言回調java靜態方法
C語言調用下面靜態方法.
public static void sayHello(String text) { System.out.println("MainActivity:showText: " + text); }
C語言回調java刷新界面
C語言調用下面Activity中方法, 彈出吐司.
public void showToast(String text) { Toast.makeText(this, text, 0).show(); }
eclipse找不到ndk選項解決辦法
NDK插件 com.android.ide.eclipse.ndk_23.0.2.1259578.jar 若是在eclipse裏配置ndk卻發現沒有配置的選項,則須要此插件,放置在eclipse/plugins下,重啓便可。
AM命令
am命令 :在adb shell裏能夠經過am命令進行一些操做如啓動activity Service 啓動瀏覽器等等
am命令的源碼在Am.java中, 在adb shell裏執行am命令實際上就是啓動一個線程執Am.java的main方法,am命令後面帶的參數都會看成運行時的參數傳遞到main函數中
am命令能夠用start子命令,而且帶指定的參數
常見參數: -a: action -d data -t 表示傳入的類型 -n 指定的組件名字
舉例: 在adb shell中經過am命令打開網頁
am start –user 0 -a android.intent.action.VIEW -d http://www.baidu.com
經過am命令打開activity
am start –user 0 -n com.ngyb.cpphello/com.ngyb.cpphello.MainActivity
execlp
execlp c語言中執行系統命令的函數
execlp() 會從PATH環境變量所指的目錄中查找符合參數file的文件找到後就執行該文件, 第二個參數開始就是執行這個文件的 args[0],args[1] 最後一個參數用(char*)NULL結束
android開發中 execlp函數對應android的path路徑爲
system/bin/目錄
調用格式
execlp(「am」, 「am」, 「start」, 「–user」,」0」,」-a」, 「android.intent.action.VIEW」, 「-d」, 「http://www.baidu.com「, (char *) NULL);
execlp(「am」, 「am」, 「start」, 「–user」,」0」, 「-n」 , 「com.ngyb.cforktest/com.ngyb.cforktest.MainActivity」,(char *) NULL);
什麼是JNI
JNI(Java Native Interface) java本地開發接口
JNI 是一個協議, 有了這個協議可使Java代碼和C/C++代碼相互調用.
爲何用JNI
1、擴展JVM功能,訪問驅動,操做硬件(物聯網、智能家居、
車載電腦)
2、效率上c/c++語言效率更高數學運算,實時渲染的遊戲上,音
視頻處理
3、 java反編譯比c語言容易, 經過JNI加強代碼安全性(加密算法放到C實現)
4、代碼移植,複用已經存在的c代碼(opencv,ffmpeg…)
怎麼用JNI
1.C/C++語言
2.掌握java jni流程
3.NDK (native develop kits )
開發環境介紹
windows下用輕量級 dev-c++
C語言基本數據類型
Java 八大基本數據類型 C基本數據類型
boolean
byte
char char
int int
float float
double double
long long
short short
C沒有boolean byte
signed unsigned 有符號無符號修飾符只能修飾整形變量
signed 有符號最高位符號位能夠表示負數
unsigned 無符號最高位仍然是數值位不能夠表示負數
輸入輸出函數
輸出函數
printf(「要輸出的內容+佔位符」,…….)
經常使用佔位符
%d - int
%ld – long int
%lld - long long
%hd – 短整型
%c - char
%f - float
%lf – double
%u – 無符號數
%x – 十六進制輸出 int 或者long int 或者short int
%o - 八進制輸出
%s – 字符串
輸入函數 Scanf
Int len;
Scanf(「%d」,&len); &取地址符號
什麼是指針
int main(void)
{
int * p; //p 是變量的名字, int * 是一個類型
//這個變量存放的是int類型變量的地址。
int i =3;
p=&i;
system(「pause」);
return 0;
}
指針常見錯誤
指針變量聲明後未賦值直接用
聲明的指針類型和指向的類型要一致
指針和指針變量的關係
指針就是地址,地址就是指針
地址就是內存單元的編號
指針變量是存放地址的變量
指針和指針變量是兩個不一樣的概念
可是要注意:一般咱們敘述時會把指針變量簡稱爲指針,實際它們含義並不同
爲何使用指針
直接訪問硬件 (opengl 顯卡繪圖)
快速傳遞數據(指針表示地址)
返回一個以上的值(返回一個數組或者結構體的指針)
表示複雜的數據結構(結構體)
方便處理字符串
*號的三種含義
*號的含義
數學運算符: 3 * 5
定義指針變量: int * p;
指針運算符(取值): *p (取p的內容(地址)在內存中的值)
指針練習互換兩個數字
swap(int* i, int* j) { // 引用傳遞
int temp = *i;
*i = *j;
*j = temp;
}
main() {
int i = 89;
int j = 10;
swap(&i, &j);
printf("i=%d\n", i);
printf("j=%d\n", j);
system("pause");
}
指針練習函數返回一個以上的值
change(int* a, int* b) {
*a = 1;
*b = 2;
}
main() {
int a = 3, b = 5;
change(&a, &b);
printf(「a=%d, b=%d\n」, a, b);
system(「pause」);
}
指針和數組的關係
數組名
int a[5]; // a是數組名,5是數組的大小,元素個數
數組名稱是個指針常量,它存放的是數組中第一個元素的地址
int a[5];
&a[0] 等價於 &a
下標和指針的關係
int a[5];
a[i] 等價於 *(a + i) // 這裏i的範圍是0~4(數組長度 -1)
指針的長度
無論什麼類型的指針都是4個字節.(64位系統8字節)
C語言爲了方便指針運算, 定義各類基本類型的指針, 每種類型的指針運算時所偏移量的值是根據類型的長度決定的.
多級指針
int i = 10;
int* p1 = &i; // 一級指針
int** p2 = &p1; // 二級指針
int*** p3 = &p2; // 三級指針
int**** p4 = &p3; // 四級指針
****p4 = 99; // 修改變量i的值爲99;
主函數獲取子函數變量地址
void function(int** p){
int i = 4;
*p = &i;
printf("子函數打印i的地址爲%#x\n", &i);
}
main(){
int* mainp;
function(&mainp);
printf("主函數打印i的地址爲%#x\n", mainp);
printf("i的值爲%d\n", *mainp);
system("pause");
}
靜態內存和動態內存
靜態內存是系統是程序編譯執行後系統自動分配,由系統自動釋放, 靜態內存是棧分配的.
動態內存是開發者手動分配的, 是堆分配的.
棧內存
* 系統自動分配
* 系統自動銷燬
* 連續的內存區域
* 向低地址擴展
* 大小固定
* 棧上分配的內存稱爲靜態內存
堆內存
* 程序員手動分配
* java:new * c:malloc
* 空間不連續
* 大小取決於系統的虛擬內存
* C:程序員手動回收free
* java:自動回收
* 堆上分配的內存稱爲動態內存
申請堆內存
malloc(memory allocate) 函數
malloc 申請一塊堆內存
free(地址); 回收內存
回收malloc 申請的堆內存
realloc re- allocate
從新申請一塊堆內存
結構體
struct Student {
int age;
float score;
char sex;
};
main() {
struct Student stu = {18, 88.5, 'M'};
}
使用結構體變量
struct Student stu = {80,55.5,'F'};
struct Student stu2;
stu2.age = 10;
stu2.score = 88.8f;
stu2.sex= ‘M';
printf("%d %f %c\n", st.age, st.score, st.sex);
// 結構體指針
struct Student * pStu;
pStu = &stu;
pStu->age 在計算機內部會被轉換爲 (* pStu).age
pStu ->age的含義: pStu所指向的結構體變量中的age這個成員
函數的指針
1.定義int (*pf)(int x, int y);
2.賦值 pf = add;
3.引用 pf(3,5);
4.結構體中不能定義函數,只能聲明函數指針
Union 聯合體
struct Date {
int year;
int month;
int day;
};
union Mix {
long i;
int k;
char ii;
};
main() {
printf("date:%d\n",sizeof(struct Date));
printf("mix:%d\n",sizeof(union Mix));
system("pause");
}
枚舉
enum WeekDay {
Monday=0,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
main() {
enum WeekDay day = Sunday;
printf("%d\n",day);
system("pause");
}
typedef
聲明自定義數據類型,配合各類原有數據類型來達到簡化編程的目的的類型定義關鍵字。
#include <stdio.h>
#include <stdlib.h>
typedef int i;
typedef long l;
main() {
i m = 10;
l n = 123123123;
printf("%d\n", m);
printf("%ld\n", n);
system("pause");
}
JNI 協議
NDK HelloWorld
1.建立一個android工程
2.java代碼中寫聲明native方法
3.建立jni目錄,編寫c代碼,方法名字要對應
4.編寫Android.mk文件
5.NDK編譯生成動態連接庫
6.java代碼load動態庫.調用native代碼
javah 生成頭文件
注意: 不一樣版本的JDK操做方式不一樣.
命令: javah <包名+類名>
JDK1.6使用方式
在工程的bin/classes目錄下, 執行javah命令.
JDK1.7使用方式
在工程的src目錄下, 執行javah命令.
NDK 簡便開發流程
1. 關聯NDK: Window -> Preferences -> Android -> NDK
2. 建立Android工程, 聲明native方法.
3. 設置函數庫名字: 右鍵工程 -> Android Tools -> App Native support
4. 使用javah生成.h的頭文件, 並把.h文件拷貝到工程下jni文件夾中.
5. c代碼提示: 右鍵工程 -> Properties -> C/C++ General -> Path and Symbols // Includes -> Add -> File system 選中如下路徑.latforms\android-18\arch-arm\usr\include
6. 把後綴名.cpp改爲.c, 實現native方法.
7. java代碼中加載動態庫, 調用native方法.
java 與 c之間的數據傳遞
public native int add(int x, int y);
public native String sayHelloInC(String s);
public native int[] arrElementsIncrease(int[] intArray);
在c代碼中使用logcat
Android.mk文件增長如下內容
LOCAL_LDLIBS += -llog
C代碼中增長如下內容
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
C代碼中使用logcat, 例:
LOGI("info\n");
LOGD("debug\n");
C語言調用java方法
C調用java空方法
public void helloFromJava(){
}
C調用java中的帶兩個int參數的方法
public int add(int x,int y) {
}
C調用java中參數爲string的方法
public void printString(String s){
}
JNI 方法簽名
簽名類型 Java類型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L全類名; 引用類型
[類型數組
C語言回調java靜態方法
C語言調用下面靜態方法.
public static void sayHello(String text) {
System.out.println("MainActivity:showText: " + text);
}
C語言回調java刷新界面
C語言調用下面Activity中方法, 彈出吐司.
public void showToast(String text) {
Toast.makeText(this, text, 0).show();
}
eclipse找不到ndk選項解決辦法
NDK插件 com.android.ide.eclipse.ndk_23.0.2.1259578.jar 若是在eclipse裏配置ndk卻發現沒有配置的選項,則須要此插件,放置在eclipse/plugins下,重啓便可。
AM命令
am命令 :在adb shell裏能夠經過am命令進行一些操做如啓動activity Service 啓動瀏覽器等等
am命令的源碼在Am.java中, 在adb shell裏執行am命令實際上就是啓動一個線程執Am.java的main方法,am命令後面帶的參數都會看成運行時的參數傳遞到main函數中
am命令能夠用start子命令,而且帶指定的參數
常見參數: -a: action -d data -t 表示傳入的類型 -n 指定的組件名字
舉例: 在adb shell中經過am命令打開網頁
am start –user 0 -a android.intent.action.VIEW -d http://www.baidu.com
經過am命令打開activity
am start –user 0 -n com.ngyb.cpphello/com.ngyb.cpphello.MainActivity
execlp
execlp c語言中執行系統命令的函數
execlp() 會從PATH環境變量所指的目錄中查找符合參數file的文件找到後就執行該文件, 第二個參數開始就是執行這個文件的 args[0],args[1] 最後一個參數用(char*)NULL結束
android開發中 execlp函數對應android的path路徑爲
system/bin/目錄
調用格式
execlp(「am」, 「am」, 「start」, 「–user」,」0」,」-a」, 「android.intent.action.VIEW」, 「-d」, 「http://www.baidu.com「, (char *) NULL);
execlp(「am」, 「am」, 「start」, 「–user」,」0」, 「-n」 , 「com.ngyb.cforktest/com.ngyb.cforktest.MainActivity」,(char *) NULL);