更新。

这个答案在我写完四年后很受欢迎,在这四年里,很多事情都发生了变化,所以我决定更新我的答案以更好地适应我们当前的现实。 答案的想法没有改变; 实施已经改变了一点。 我的英语也发生了变化,它已经有了很大的改进,所以现在每个人的答案都更容易理解。

请查看repo,以便下载并运行我将在下面显示的代码。

答案

在我展示代码之前,请在下图中采取很多措施。

每个操作系统都有其UI和特性,因此我们打算在这方面为每个平台编写特定的代码。 另一方面,我们打算使用C ++编写所有逻辑代码,业务规则和可共享的东西,因此我们可以将相同的代码编译到每个平台。

在图中,您可以看到最低级别的C ++层。 所有共享代码都在此段中。 最高级别是常规的Obj-C / Java / Kotlin代码,这里没有新闻,困难的部分是中间层。

iOS中间层很简单; 您只需要将项目配置为使用Obj-c的变体(即Objective-C ++)进行构建,并且完全可以访问C ++代码。

在Android方面,事情变得更加困难,Android上的Java和Kotlin语言都在Java虚拟机下运行。 因此访问C ++代码的唯一方法是使用JNI,请花时间阅读JNI的基础知识。 幸运的是,今天的Android Studio IDE在JNI方面有很大的改进,在编辑代码时会显示很多问题。

代码逐步完成

我们的示例是一个简单的应用程序,您可以将文本发送到CPP,并将该文本转换为其他内容并将其返回。 这个想法是,iOS将发送“Obj-C”,Android将从他们各自的语言发送“Java”,CPP代码将创建一个文本作为跟随“cpp说你好<< text received>>”。

共享CPP代码

首先,我们将创建共享的CPP代码,为此我们有一个简单的头文件,其中包含接收所需文本的方法声明:

#include

const char *concatenateMyStringWithCppString(const char *myString);

CPP实施:

#include

#include "Core.h"

const char *CPP_BASE_STRING = "cpp says hello to %s";

const char *concatenateMyStringWithCppString(const char *myString) {

char *concatenatedString = new char[strlen(CPP_BASE_STRING) + strlen(myString)];

sprintf(concatenatedString, CPP_BASE_STRING, myString);

return concatenatedString;

}

Unix的

一个有趣的好处是,我们也可以使用相同的代码用于Linux和Mac以及其他Unix系统。 这种可能性特别有用,因为我们可以更快地测试我们的共享代码,因此我们将创建一个Main.cpp,如下所示,从我们的机器执行它,看看共享代码是否正常工作。

#include

#include

#include "../CPP/Core.h"

int main() {

std::string textFromCppCore = concatenateMyStringWithCppString("Unix");

std::cout << textFromCppCore << '\n';

return 0;

}

要构建代码,您需要执行:

$ g++ Main.cpp Core.cpp -o main

$ ./main

cpp says hello to Unix

iOS版

是时候在移动端实施了。 至于iOS有一个简单的集成,我们从它开始。 我们的iOS应用程序是一个典型的Obj-c应用程序,只有一个区别; 文件是jstring而不是const char *.即它是一个Obj-C ++应用程序,而不是Obj-C应用程序。

为了更好的组织,我们创建CoreWrapper.mm如下:

#import "CoreWrapper.h"

@implementation CoreWrapper

+ (NSString*) concatenateMyStringWithCppString:(NSString*)myString {

const char *utfString = [myString UTF8String];

const char *textFromCppCore = concatenateMyStringWithCppString(utfString);

NSString *objcString = [NSString stringWithUTF8String:textFromCppCore];

return objcString;

}

@end

该类有责任将CPP类型和调用转换为Obj-C类型和调用。 一旦你可以在Obj-C上的任何文件上调用CPP代码,这不是强制性的,但是它有助于保持组织,并且在你的包装文件之外你维护一个完整的Obj-C样式代码,只有包装文件成为CPP样式。

将包装器连接到CPP代码后,可以将其用作标准的Obj-C代码,例如视图控制器”

#import "ViewController.h"

#import "CoreWrapper.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

NSString* textFromCppCore = [CoreWrapper concatenateMyStringWithCppString:@"Obj-C++"];

[_label setText:textFromCppCore];

}

@end

看看应用程序的外观:

Android的

现在是Android集成的时候了。 Android使用Gradle作为构建系统,而使用CMake的C / C ++代码。 所以我们需要做的第一件事就是在gradle文件上配置CMake:

android {

...

externalNativeBuild {

cmake {

path "CMakeLists.txt"

}

}

...

defaultConfig {

externalNativeBuild {

cmake {

cppFlags "-std=c++14"

}

}

...

}

第二步是添加CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.4.1)

include_directories (

../../CPP/

)

add_library(

native-lib

SHARED

src/main/cpp/native-lib.cpp

../../CPP/Core.h

../../CPP/Core.cpp

)

find_library(

log-lib

log

)

target_link_libraries(

native-lib

${log-lib}

)

在CMake文件中,您需要添加将在项目中使用的CPP文件和头文件夹,在我们的示例中,我们添加了jstring文件夹和Core.h / .cpp文件。 要了解有关C / C ++配置的更多信息,请阅读它。

现在核心代码是我们应用程序的一部分,是时候创建桥梁,为了使事情更简单和有条理,我们创建一个名为CoreWrapper的特定类作为JVM和CPP之间的包装:

public class CoreWrapper {

public native String concatenateMyStringWithCppString(String myString);

static {

System.loadLibrary("native-lib");

}

}

请注意,此类有一个jstring方法,并加载一个名为const char *的本机库。这个库是我们创建的库,最后,CPP代码将成为共享对象jstring文件嵌入我们的APK,JNIEnv*将加载它。 最后,当您调用本机方法时,JVM会将调用委托给已加载的库。

现在Android集成中最奇怪的部分是JNI; 我们需要一个cpp文件,在我们的例子中是“native-lib.cpp”:

extern "C" {

JNIEXPORT jstring JNICALL Java_ademar_androidioscppexample_CoreWrapper_concatenateMyStringWithCppString(JNIEnv *env, jobject /* this */, jstring myString) {

const char *utfString = env->GetStringUTFChars(myString, 0);

const char *textFromCppCore = concatenateMyStringWithCppString(utfString);

jstring javaString = env->NewStringUTF(textFromCppCore);

return javaString;

}

}

您将注意到的第一件事是jstring这部分是JNI正确使用我们的CPP代码和方法链接所必需的。 您还将看到JNI用于与JVM一起使用的一些符号,如const char *和jstring.为了理解这些内容的含义,有必要花一些时间阅读它,因为本教程的目的只是将这些内容视为样板。

一个重要的事情,通常是许多问题的根源是方法的名称; 它需要遵循“Java_package_class_method”模式。 目前,Android studio对它有很好的支持,因此它可以自动生成这个样板,并在它正确或未命名时显示给你。 在我们的示例中,我们的方法名为“Java_ademar_androidioscppexample_CoreWrapper_concatenateMyStringWithCppString”,因为“ademar.androidioscppexample”是我们的包,所以我们替换“。” 通过“_”,CoreWrapper是我们链接本机方法的类,“concatenateMyStringWithCppString”是方法名称本身。

正如我们正确声明的方法是分析参数的时候,第一个参数是jstring的指针,这是我们访问JNI的方式,对于我们很快就会进行转换至关重要。 第二个是const char *它是您用来调用此方法的对象的实例。 您可以将其视为java“this”,在我们的示例中我们不需要使用它,但我们仍然需要声明它。 在这个jobject之后,我们将接收该方法的参数。 因为我们的方法只有一个参数 - 一个字符串“myString”,所以我们只有一个名字相同的“jstring”。 还要注意我们的返回类型也是一个jstring。 这是因为我们的Java方法返回一个String,有关Java / JNI类型的更多信息,请阅读它。

最后一步是将JNI类型转换为我们在CPP端使用的类型。 在我们的例子中,我们正在将jstring转换为const char *,将其转换为CPP,得到结果并转换回jstring。正如JNI上的所有其他步骤一样,并不难; 它只是用于电镀,所有的工作都是通过我们拨打GetStringUTFChars和NewStringUTF时收到的JNIEnv*参数完成的。之后我们的代码已准备好在Android设备上运行,让我们一起来看看。

安卓是java ios c_如何为Android和iOS使用相同的C ++代码?相关推荐

  1. Java xinge 消息推送Android和IOs

    xinge消息推送: 比如就像淘宝一样,用户下完订单,就会给用户提示一条信息:订单核对等等.如果我们也想实现类似的功能呢? 一.往pom.xml文件中引入包 <dependency>< ...

  2. 相同点安卓和iosui的相同点_9个Android和iOS之间的交互差异点

    9个Android和iOS之间的交互差异点 十一月 8, 2019 发表于: 交互设计. 评论 Sponsor 移动端开发的主要载体是Android和iOS,在开发的时候出于某些原因而采用一套设计方案 ...

  3. android ios 上传图片到服务器,Android与iOS手机照片互传技巧分享

    眼下,手握Android与iOS双手机的用户不在少数,比如一个移动或联通版的iPhone合约机再加上一个电信版的Android合约机.那么,当平常使用这两类不同操作系统手机时,各自手机中存储的照片又该 ...

  4. H5页面跳转至应用市场(Android/ios)(判断是Android还是ios)

    var u = navigator.userAgent;var isAndroid = u.indexOf("Android") > -1 || u.indexOf(&quo ...

  5. android和ios比例,91分析Android与IOS游戏及软件下载比例数据

    作为最受欢迎的两个手机系统,iOS与Android向来竞争激烈,今天对这两个系统近期的市场份额和用户比例做了如下详细分析: 一.IOS与android市场份额对比 近几年很多手机厂商依靠Android ...

  6. 为什么Android没有iOS那么顺滑

    本文转自:http://www.williamlong.info/archives/2918.html 这是一部分针对android和ios的讨论 为什么Android没有iOS那么顺滑 1.omf ...

  7. Android vs iOS 程序开发:我该选哪一个?

    移动应用程序开发是软件生产中增长最稳定的领域之一.几年前来移动应用程序数量激增,对快速便捷应用程序的需求一直在增长.仅是在2020年,据估计用户将大约87%的在线时间用于移动应用程序,也就是手机的Ap ...

  8. Android Swift iOS开发:语言与框架对比

    转载自:http://www.infoq.com/cn/articles/from-android-to-swift-ios?utm_campaign=rightbar_v2&utm_sour ...

  9. WebRTC 系列(二、本地通话,H5、Android、iOS)

    WebRTC 系列(一.简介)​​​​​​​ 一.整体流程 有了上一篇 WebRTC 简介的基础,我们知道了 WebRTC 的工作流程,接下来就是需要用代码去实现这个流程了.对于不同端,实现起来的难易 ...

最新文章

  1. 工作上996,生活上669,并不是什么难事儿!
  2. python多线程执行其他模块的文件_python并发编程--进程线程--其他模块-从菜鸟到老鸟(三)...
  3. MySQL 覆盖索引
  4. cocos2d-x游戏开发(十五)游戏加载动画loading界面
  5. word2013标题编号变成黑框
  6. Arraylist添加5个学生对象,按成绩降序, 删除前三之后的学生
  7. 使用 Python 切割图片
  8. h5 表单居中_3分钟学会易企秀H5操作(基础篇)
  9. django url 生效_Django-url配置和详解
  10. python查找关键字所属行_Python查找文件有多牛?男默女泪!!!
  11. java给视频添加水印_用java实现给图片增加图片水印或者文字水印(也支持视频图像帧添加水印)...
  12. android音乐播放器app源码
  13. shl归纳推理测试题库_笔经总结含征服shl功略
  14. 如何优化Flash动画使文件更小播放更流畅
  15. java钟表动画_钟表动画的实现
  16. [笔记] 当当音乐人:免费将Midi转化为WAV
  17. 小程序-JAVA服务端解密与微信绑定的手机号
  18. 520到了,教你做个JavaWeb表白墙小项目
  19. 编译内核 make modules_install报错make[1]: *** [arch/x86/crypto/aegis128-aesni.ko] Error 1 Makefile:1281: r
  20. 高级前端成长训练营|和阿龙一起学前端曝光——走进前端开发世界

热门文章

  1. java 获取组件大小_java - 如何初始化取决于组件大小的图像抓取? - 堆栈内存溢出...
  2. java private 内部类_java中外部类是否可以访问内部类的private 元素呢?
  3. get请求可以传body吗_详解用 Go 语言解析各种 HTTP 请求的方法
  4. mongodb创建普通用户并授权readWrite角色,并允许访问某一数据库
  5. 数据库开启了闪回和归档,关闭归档日志alter database noarchivelog的时候报错:ORA-38781: cannot disable media recovery
  6. 每个做DBA的孩纸都是上辈子被drop的db
  7. oracle11 rman全备,Oracle 11g非归档模式下mount状态RMAN究竟能不能进行全备?
  8. JAVA基础系列:Arrays.binarySearch二分查找
  9. markdownpad2下载安装教程
  10. Java的设计模式 之 简单的工厂模式(一)