欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++在Java、Android和Objective-C三大平臺(tái)下實(shí)現(xiàn)混合編程

 更新時(shí)間:2016年08月26日 17:31:02   作者:Wiki  
本文主要介紹C/C++在Java、Android和Objective-C三大平臺(tái)下實(shí)現(xiàn)混合編程,這里舉例說明實(shí)現(xiàn)不同平臺(tái)用C/C++實(shí)現(xiàn)編程的方法,有興趣的小伙伴可以參考下

Android和iOS開發(fā)都支持C++開發(fā),可以一套代碼多平臺(tái)使用。同時(shí)C++難以反編譯的特性也可以為Android開發(fā)帶來代碼的保密,另一native特性也可以提高代碼的運(yùn)行效率。

一、為什么使用C/C++

  1. 便于移植,用C/C++寫得庫可以方便在其他的平臺(tái)上再次使用。
  2. 代碼的保護(hù),由于java層代碼很容易被反編譯,而C/C++庫反匯難度較大。
  3. 提高程序的執(zhí)行效率,將要求高性能的應(yīng)用邏輯使用C/C++開發(fā),從而提高應(yīng)用程序的執(zhí)行效率。
  4. 訪問現(xiàn)有開源庫,需要訪問底層的API或引用一些只有C/C++的庫。

二、開發(fā)工具介紹

盡管Android Studio可以同時(shí)編寫C++和Java代碼,寫完就可以編譯運(yùn)行,但是對(duì)聯(lián)想和錯(cuò)誤提示并不是非常友好,個(gè)人建議C++的整體代碼使用Visual Studio或Xcode編譯開發(fā),聯(lián)想功能非常友好,編譯速度很快,調(diào)試也非常方便。

  1. Visual Studio(PC)
  2. Xcode(Mac)
  3. Android Studio(多平臺(tái))
  4. eclipse(多平臺(tái))

三、第一行代碼

1. 如何在Objective-C項(xiàng)目中使用C++;

在Objective-C使用C/C++非常簡(jiǎn)單,僅僅需要把.m后綴的文件改成.mm即可使用C++,我們通常不會(huì)把.mm的文件寫到整個(gè)項(xiàng)目都有,而是設(shè)計(jì)一個(gè)接口,用來做兩個(gè)語言之間的橋梁,他們之間的交互僅僅在這個(gè)接口。

要點(diǎn):String類型轉(zhuǎn)換

// Objective-C(NSString) -> C++(std::string)
NSString * ocString = @"Hello World,OC";
std::string cppString = [ocString UTF8String];
std::cout<<cppString<<std::endl;
// C++(std::string) -> Objective-C(NSString)
std::string cppString2 = "Hello World,C++";
NSString *ocString2= [NSString stringWithCString:cppString2.c_str() encoding:[NSString defaultCStringEncoding]];
NSLog(@"%@",ocString2);

記得要include相關(guān)的文件

#include <stdio.h>
#include <iostream>

2.在普通的JAVA項(xiàng)目中使用JNI編程

由于我是在MAC下辦公,所以這里就介紹如何在MAC下進(jìn)行JNI開發(fā),在Windows平臺(tái)下的Virtual Studio也很簡(jiǎn)單。

第一步:在Xcode下創(chuàng)建一個(gè)普通的C++項(xiàng)目

第二步:關(guān)聯(lián)JavaVM的Framework

路徑:

/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaNativeFoundation.framework/

第三步:創(chuàng)建頭文件,用于和Java交互 cn_taoweiji_nativemodule_NativeDemo.h

#include <JavaVM/jni.h>
#ifndef _Included_cn_taoweiji_nativemodule_NativeDemo
#define _Included_cn_taoweiji_nativemodule_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
 JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add
 (JNIEnv *, jclass, jint, jint);
 JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_say
 (JNIEnv *, jclass, jstring);
 JNIEXPORT jstring JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_getInfo
 (JNIEnv *, jclass);

 JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava
 (JNIEnv *, jclass, jobject);

#ifdef __cplusplus
}
#endif
#endif

第四步:創(chuàng)建實(shí)現(xiàn) NativeDemo.cpp

#include "cn_taoweiji_nativemodule_NativeDemo.h"
#include <string>
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint param1, jint param2)
{
 jint result = param1 + param2;
 return result;
}
JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_say(JNIEnv *env, jclass, jstring param)
{
 // std::string -> jstring
 const char *param_char = env->GetStringUTFChars(param, NULL);
 std::string str = param_char;
}
JNIEXPORT jstring JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_getInfo(JNIEnv *env, jclass)
{
 // jstring -> std::string
 std::string str = "Hi,I am C++.";
 jstring result = env->NewStringUTF(str.c_str());
 return result;
}
JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava(JNIEnv * env, jclass, jobject obj)
{
 // 調(diào)用Java方法
 jclass cls = env->FindClass("cn/taoweiji/nativemodule/NativeDemo");
 //int subtract(int param1, int param2) -> (II)I
 jmethodID mid = env->GetMethodID(cls, "subtract", "(II)I");
 int result = (int) env->CallIntMethod(obj, mid, 10, 2);
// std::cout<<result<<std::endl;
 //常見類型轉(zhuǎn)換例子
 //String getInfo();
 //-> ()Ljava/lang/String;

 //PackageInfo getPackageInfo(String packageName, int flags);
 //-> (Ljava/lang/String;I)Landroid/content/pm/PackageInfo;;

}

第五步:編譯生成JNI文件,按 ⌘+B (Product -> Build).

編譯后文件

根據(jù)自己的電腦環(huán)境,查找編譯后的文件,我的路徑是

/Users/Wiki/Library/Developer/Xcode/DerivedData/DEMO_MAC_JNI-clxymnzifegyfaajsaattzgxqfbr/Build/Products/Debug/DEMO_MAC_JNI

第六步:編寫JNI接口

package cn.taoweiji.nativemodule;
/**
 * 包名和類名稱一定要和前面的C++頭文件對(duì)應(yīng)
 * cn_taoweiji_nativemodule_NativeDemo.h
 */
public class NativeDemo {
 public static native int add(int param1, int param2);
 public static native void say(String name);
 public static native String getInfo();
 public static native void nativeToJava(NativeDemo nativeDemo);
 public int subtract(int param1, int param2) {
 System.out.println("NativeDemo:" + String.format("%s - %s = %s", param1, param2, param1 - param2));
 return param1 - param2;
 }
}


第七步:調(diào)用C++

public class Main {
 static {
 System.load("/Users/Wiki/Library/Developer/Xcode/DerivedData/DEMO_MAC_JNI-clxymnzifegyfaajsaattzgxqfbr/Build/Products/Debug/DEMO_MAC_JNI");
 }
 public static void main(String[] args) {
 System.out.println("Hello World!");
 int result = NativeDemo.add(1, 2);
 System.out.println("1+2=" + String.valueOf(result));
 NativeDemo.say("Hello,I am Java.");
 System.out.println("getInfo:" + NativeDemo.getInfo());
 NativeDemo.nativeToJava(new NativeDemo());
 }
}

3. 在ANDROID項(xiàng)目中使用NDK

Android的JNI開發(fā),C++文件必須編寫在獨(dú)立的module里面,Java接口代碼可以編寫在app(module),也可以和C++放在同一個(gè)module,通過gradle關(guān)聯(lián)。詳細(xì)代碼請(qǐng)自行下載demo瀏覽

gradle配置(NativeModule)
apply plugin: 'com.android.library'
android {
 compileSdkVersion 23
 buildToolsVersion "24.0.0 rc2"
 defaultConfig {
 minSdkVersion 14
 targetSdkVersion 23
 versionCode 1
 versionName "1.0"
 }
 buildTypes {
 release {
  minifyEnabled false
  proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  ndk {
  moduleName "joyrun"
  stl "stlport_static"
  ldLibs "log"http://用于解決__android_log_print
  abiFilters "armeabi", "armeabi-v7a", "x86", "x86_64", "arm64-v8a"
  //add -fexceptions to allow throw error
  //add -w to "format not a string literal and no format arguments [-Werror=format-security"
  cFlags "-w -fexceptions"
  }
 }
 }
}
dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
}

編寫JNI接口

// NativeDemo.java
package cn.taoweiji.nativemodule;
public class NativeDemo {
 public static native int add(int param1, int param2);
}

編寫C++接口代碼,JNI文件目錄默認(rèn)是module/src/main/jni,可以通過gradle配置改變

// cn_taoweiji_nativemodule_NativeDemo.h
#include <jni.h>
#ifndef _Included_cn_taoweiji_nativemodule_NativeDemo
#define _Included_cn_taoweiji_nativemodule_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class: cn_taoweiji_nativemodule_NativeDemo
 * Method: add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
// NativeDemo.cpp
#include "cn_taoweiji_nativemodule_NativeDemo.h"
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint param1, jint param2)
{
 jint result = param1 + param2;
 return result;
}

調(diào)用

// 靜態(tài)加載
static {
 System.loadLibrary("joyrun");
}
//調(diào)用
int result = NativeDemo.add(1,2);
Log.i("1+2=",String.valueOf(result));

四、NDK開發(fā)要點(diǎn)

編譯文件分析

將NativeModule編譯后生成的aar文件后綴改成.zip解壓,可以發(fā)現(xiàn)里面有個(gè)jni文件,打開可以看到”armeabi”, “armeabi-v7a”, “x86”, “x86_64”, “arm64-v8a”等文件夾,再打開可以看到是以lib前綴的so格式文件,這就是編譯后的native層文件,我們平常引用的第三方庫(百度地圖)也是要添加這些文件到我們的libs文件夾,不同的名稱代表著不同平臺(tái)相關(guān)的編譯文件,市面上大多數(shù)的手機(jī)都是arm架構(gòu)CPU,x86架構(gòu)的手機(jī)幾乎沒人用(genymotion模擬器屬于x86平臺(tái)),所以我們通常發(fā)布APP不會(huì)考慮x86平臺(tái),僅僅添加armeabi文件即可,但是在開發(fā)過程中建議也添加x86的so文件,以方便我們?cè)谀M器上運(yùn)行。

運(yùn)行庫

Android平臺(tái)帶有一個(gè)微型的C運(yùn)行庫支持庫,成為系統(tǒng)運(yùn)行庫。該運(yùn)行庫不支持一下特性:C標(biāo)準(zhǔn)庫、異常支持、RTTI支持。NDK提供了用于補(bǔ)充系統(tǒng)運(yùn)行庫功能的一些額外的C++運(yùn)行庫。

C++運(yùn)行庫 C++異常支持 C++RTTI C++標(biāo)準(zhǔn)庫
系統(tǒng)庫 No No No
GAbi++ No Yes No
STLport No Yes Yes
GNU STL Yes Yes Yes

1.STLportSTLport是一個(gè)開源的、多平臺(tái)的C標(biāo)準(zhǔn)庫實(shí)現(xiàn)。它提供一個(gè)C標(biāo)準(zhǔn)庫頭文件的完整集合以及對(duì)RTTI的支持。

2.GNU STLGNU標(biāo)準(zhǔn)C庫,也叫l(wèi)ibstdc-v3,是Android NDK最全面的標(biāo)準(zhǔn)C運(yùn)行庫。它是一個(gè)正在開發(fā)的、以實(shí)現(xiàn)ISO標(biāo)準(zhǔn)C庫為目標(biāo)的開源項(xiàng)目。

gradle配置

  1. STL運(yùn)行庫引用
  2. “armeabi”, “armeabi-v7a”, “x86”, “x86_64”, “arm64-v8a”等平臺(tái)配置
  3. C++輸出logcat配置
  4. 一個(gè)編譯異常解決
  5. 異常捕獲
// 生成so文件的名稱
moduleName "joyrun"
// 引入STL標(biāo)準(zhǔn)庫
stl "stlport_static"http://gnustl_static
//用于解決__android_log_print
ldLibs "log"
abiFilters "armeabi", "armeabi-v7a", "x86", "x86_64", "arm64-v8a" //添加編譯的平臺(tái)
//add -fexceptions to allow throw error
//add -w to "format not a string literal and no format arguments [-Werror=format-security"
cFlags "-w -fexceptions"

LOGCAT輸出

#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "tag_joyrun", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "tag_joyrun", __VA_ARGS__)
LOGE("Hello Logcat");

類型轉(zhuǎn)換

// std::string -> jstring
std::string str = "Hello World";
jstring result = env->NewStringUTF(str.c_str());
// jstring -> std::string
jstring param;
const char *param_char = env->GetStringUTFChars(param, NULL);
std::string str = param_char;
// jboolean 兩個(gè)值 JNI_TRUE、JNI_FALSE

C++調(diào)用JAVA代碼

//Java

public static native void nativeToJava(NativeDemo nativeDemo);
public int subtract(int param1, int param2) {
Log.e("NativeDemo", String.format("%s - %s = %s", param1, param2, param1 - param2));
return param1 - param2;
}

//C++

JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava(JNIEnv * env, jclass, jobject obj)
{
 // 調(diào)用Java方法
 jclass cls = env->FindClass("cn/taoweiji/nativemodule/NativeDemo");
 jmethodID mid = env->GetMethodID(cls, "subtract", "(II)I");
 int result = (int) env->CallIntMethod(obj, mid, 10, 2);

 //常見類型轉(zhuǎn)換例子
 //String getInfo();
 //-> ()Ljava/lang/String;
 //PackageInfo getPackageInfo(String packageName, int flags);
 //-> (Ljava/lang/String;I)Landroid/content/pm/PackageInfo;;
}

一鍵生成從JAVA到C++接口代碼腳本

文件:autojavah.sh

#!/bin/sh
export ProjectPath=$(cd "../$(dirname "$1")"; pwd)
export TargetClassName="co.runner.app.jni.NativeDemo"
export SourceFile="${ProjectPath}/app/src/main/java"
export TargetPath="${ProjectPath}/jni-joyrun/src/main/jni"
cd "${SourceFile}"
javah -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"
echo -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"

五、C++面向?qū)ο蠹皹?biāo)準(zhǔn)庫入門

C++類定義

// Demo.hpp
#ifndef Demo_hpp
#define Demo_hpp
#include <stdio.h>
#include <string>
class Demo{
public:
 std::string name;
 int age = 0;
 void say();
 static int add(int param1,int param2)
 {
 return param1 + param2;
 }
};
#endif /* Demo_hpp */

類方法的實(shí)現(xiàn)

// Demo.cpp
#include "Demo.hpp"
#include <iostream>
void Demo::say()
{
 std::cout<<"name = "<<name<<",age = "<<age<<std::endl;
}

對(duì)象創(chuàng)建及訪問對(duì)象的成員

//對(duì)象創(chuàng)建
Demo d1;
Demo * d2 = new Demo;
// 運(yùn)算符訪問
d1.say();
// 指針訪問
d2->say();
//靜態(tài)函數(shù)訪問
int result = Demo::add(1,2);
std::cout<<"1 + 2 = "<<result<<std::endl;

LIST鏈表

//include相關(guān)文件
#include <stdio.h>
#include <iostream>
#include <list>
#include "Demo.hpp"
// 鏈表定義
std::list<Demo> * demos = new std::list<Demo>;
Demo * demo = new Demo;
demo->name = "Wiki";
demo->age = 24;
// 在后面插入數(shù)據(jù)
demos->push_back(*demo);
demo = new Demo;
demo->name = "Wiki2";
demo->age = 25;
// 在前面插入數(shù)據(jù)
demos->push_front(*demo);
// 順序鏈表遍歷
for (std::list<Demo>::iterator iter = demos->begin(); iter != demos->end(); ++iter) {
 iter->say();
}
// 反順序鏈表遍歷
for (std::list<Demo>::reverse_iterator iter = demos->rbegin(); iter != demos->rend(); ++iter) {
 iter->say();
}
// 獲取指定位置元素
std::list<Demo>::iterator iter = demos->begin();
advance(iter, 1);
iter->say();

指針、引用和值

在C++中,函數(shù)可以用許多不同的方法傳遞參數(shù),比如通過指針、引用或是直接傳值。

// 通過指針
void handle1(Demo *p);
// 通過引用
void handle1(Demo& p);
// 通過值
void handle1(Demo *demo);

堆和棧的理解

棧(stack):由操作系統(tǒng)自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧;

堆(heap): 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收,分配方式倒是類似于鏈表。

Demo d1;//棧
Demo * d2 = new Demo;//堆
char c; //棧上分配
char *p = new char[3]; //堆上分配,將地址賦給了p;

垃圾回收

new和C++ delete運(yùn)算符用于動(dòng)態(tài)分配和撤銷內(nèi)存的運(yùn)算符,自己new出來的對(duì)象就要通過delete釋放內(nèi)存。

delete demos;

六、開發(fā)中常用的方法及注意事項(xiàng)(坑)

  1. 時(shí)間戳獲取方法 long time = time(0);
  2. 注意so文件防盜用問題。
  3. 盡量避免調(diào)用與平臺(tái)有關(guān)的方法,避免移植帶來問題。
  4. JNI接口的包名不能帶有下劃線‘_'。

相關(guān)源代碼:

Android: https://github.com/taoweiji/DEMO_NDK
Objective-C: https://github.com/taoweiji/DEMO_CPP_OC
MAC-JNI: https://github.com/taoweiji/DEMO_MAC_JNI

 以上就是C/C++ 在Android和java,Objective-C 三大平臺(tái)下開發(fā)應(yīng)用的資料整理,后續(xù)繼續(xù)整理相關(guān)文章,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • Flutter?LinearProgressIndicator使用指南分析

    Flutter?LinearProgressIndicator使用指南分析

    這篇文章主要為大家介紹了Flutter?LinearProgressIndicator使用指南分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Android TextView多文本折疊展開效果

    Android TextView多文本折疊展開效果

    這篇文章主要為大家詳細(xì)介紹了Android TextView多文本折疊展開效果的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作

    Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作

    這篇文章主要介紹了Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android徹底清除APP數(shù)據(jù)的兩種方案總結(jié)

    Android徹底清除APP數(shù)據(jù)的兩種方案總結(jié)

    大家在用Android手機(jī)的時(shí)候肯定都遇到過內(nèi)存剩余空間越來越小的情況,所以下面這篇文章主要給大家介紹了關(guān)于Android徹底清除APP數(shù)據(jù)的兩種方案,需要的朋友可以參考下
    2021-11-11
  • Android編程實(shí)現(xiàn)識(shí)別與掛載U盤的方法

    Android編程實(shí)現(xiàn)識(shí)別與掛載U盤的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)識(shí)別與掛載U盤的方法,對(duì)比分析了Android針對(duì)U盤的識(shí)別與掛載技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-02-02
  • android實(shí)現(xiàn)清理緩存功能

    android實(shí)現(xiàn)清理緩存功能

    這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)清理緩存,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Kotlin作用域函數(shù)之間的區(qū)別和使用場(chǎng)景詳解

    Kotlin作用域函數(shù)之間的區(qū)別和使用場(chǎng)景詳解

    這篇文章主要給大家介紹了關(guān)于Kotlin作用域函數(shù)之間的區(qū)別和使用場(chǎng)景的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • android 使用Xml文件定義Shape方式

    android 使用Xml文件定義Shape方式

    這篇文章主要介紹了android 使用Xml文件定義Shape方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android更改EditText下劃線顏色樣式的方法

    Android更改EditText下劃線顏色樣式的方法

    Android 里 EditText下劃線有默認(rèn)的顏色樣式,如何修改其顏色,而且想單獨(dú)定義某一個(gè)界面的顏色樣式呢。下面這篇文章主要介紹了Android更改EditText下劃線顏色樣式的方法,需要的朋友可以參考下
    2017-01-01
  • Android開發(fā)懸浮按鈕 Floating ActionButton的實(shí)現(xiàn)方法

    Android開發(fā)懸浮按鈕 Floating ActionButton的實(shí)現(xiàn)方法

    這篇文章主要介紹了Android開發(fā)懸浮按鈕 Floating ActionButton的實(shí)現(xiàn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09

最新評(píng)論