在Android和iOS设备上调用C++代码

不少Android和iOS项目中,因为种种原因不得不调用C/C++代码。这篇文章主要讲述如何通过Objective-C++、NDK技术在iOS及Android设备上调用C/C++代码。

通过这篇文章对我的启发是:
可以通过C++写一个socket长连接的功能模块。可以通过这种方法来实现安卓和苹果都能共用这个模块,不用安卓和苹果各自开发长连接模块了。
socket长连接对一部分人本来就陌生。并且维护一份代码比维护两份代码要容易的多。
以后我要把我的Object C写的socket长连接转换成C++的长连接。哥本来就是C++出身转Objec C的。

转载文章地址:https://my.oschina.net/baratsemet/blog/419692
主要工作原理
这里写图片描述
主要工作原理,如上图所示。Google Android提供NDK以便支持C/C++代码,而iOS可以通过Objective-C++(*.mm)来支持C/C++代码的编译运行。如果有朋友钻研过Cocos2d-x的话,应该对上述这些内容非常熟悉。好了,废话不多说,开始提供干货。

需要调用的C++代码

我们先编写一个简单的C++代码,以便能够在Android和iOS设备上调用。为了简单起见,也为了能够充分展示操作过程,我们设计如下的C++类:

MyClz.h文件

include

class MyClz {
public:
double getSum(const double num1, const double num2);
};
在上述MyClz.h头文件中,我们引入了iostream,并声明了一个类MyClz,其中包含一个公开的方法getSum,其作用很明显:传入两个double类型的数值,计算并返回两个数的和。

MyCLz.cpp文件

include “MyClz.h”

double MyClz::getSum(const double num1, const double num2){
return num1 + num2;
}

int main() {
return 0;
}
cpp文件中,我们实现了头文件MyClz.h中声明的getSum方法的内容,计算两个数的和并将其反馈给调用者。

接下来,我们来看看,如何在Android和iOS设备上调用上述MyClz类中的getSum方法。

在Android设备调用

1.下载并配置Android Studio
本例中,采用了最新版的Android Studio(v1.2.1.1)作为开发环境。下载并安装,同时根据自己的需要下载相应的Android SDK并配置好各项开发环境。

请注意:如下网页需要「科学上网」才能正常访问
Android Studio:http://developer.android.com/sdk/index.html

2.下载并配置NDK
NDK是Google提供的一套用以在Android设备上调用C/C++代码的工具集。某些情况下,可能没有办法使用Java语言完成的任务,只能借助底层的本地代码(native code)实现。这时,NDK就会派上用场。到如下地址下载NDK并将其解压到本地磁盘的某个路径即可。

请注意:如下页面需要「科学上网」才能正常访问
Android NDK:http://developer.android.com/tools/sdk/ndk/index.html

3.新建一个Android项目
在Android Studio中新建一个Android项目。如果习惯了Eclipse+ADT的朋友,可能会对Android Studio感到无比蛋疼。但是,根据我的使用经验来看,Android Studio完全可以取代Eclipse+ADT成为今后的主流Android IDE。再者,这玩意儿既然是Google主推的产品,应该会越来越受到重视,所以早点习惯才好。 新建好的Android项目的大体目录结构如下图所示:
这里写图片描述

上述目录结构中,对开发者而言非常关键的几个文件及文件夹有:
{project_home}/app Android项目的主体目录
{project_home}/app/build.gradle app构建配置文件
{project_home}/app/src 项目源代码
{project_home}/local.properties SDK、NDK路径配置文件

4.修改{project_home}/local.properties文件
该文件种默认有一行,是指定Android SDK所在的文件路径,因为我们项目中还需要使用NDK。修改该文件,再文件后面加入如下内容,以便告诉IDE需要使用的NDK路径:

ndk.dir=/YourPathToAndroidNDK/Android-NDK-r10d
5.修改{project_home}/app/build.gradle文件
在该文件中「适当的位置处」加入NDK配置内容如下:

android {
….
defaultConfig {

ndk {
moduleName “HelloJNI”
stl “stlport_static”
}
}

}
在文件中加入上述内容时,尤其需要注意moduleName属性设置的值,这里我将其命名为HelloJNI,该名称可以随便写。在JNI代码中需要导入lib时将需要填写这个值(后续文章种将会提到)。

6.在{project_home}/app/src/main目录中新增jni目录
在上述目录中新增一个jni目录,并将编写好的MyClz.h和MyClz.cpp文件放入其中。

7.在{project_home}/app/src/main/jni目录中新增MyClz-JNI.cpp文件
因为之前编写的MyClz.h和MyClz.cpp文件不符合JNI的规范(客户提供的cpp文件很少会有符合JNI规范的),因此我们需要编写一个符合JNI规范的cpp文件。
到这一步时,{project_home}/app/src/main/jni目录中应该包含了MyClz.h、MyClz.cpp及MyClz-JNI.cpp三个文件。

8.编写MyClz-JNI.cpp文件的内容

#include <jni.h>
 #include <stdio.h>
 #include <string.h>

 #include "MyClz.h"

 extern "C" {

     MyClz* clz;

     JNIEXPORT jdouble JNICALL Java_com_baratsemet_android_wrapper_HelloWrapper_getSumFromJNI(JNIEnv* env,jdouble num1, jdouble num2) {
         return clz->getSum(num1,num2);
     }
 };

请注意:
上述类中的方法名称,是符合JNI规范的方法名。该方法名必须是Java_包名类名方法名(参数名) 这种方式。若对此不明白的朋友,可以自行查阅JNI相关文档,这里就不在详述。
编写HelloWrapper.java文件 从上述MyClz-JNI.cpp文件中的方法名中可以看出:我们将要编写的HelloWrapper.java文件所在的包应该是:com.baratsemet.android.wrapper,因此在{project_home}/app/main/java中新建上述包,并在其中新建HelloWrapper.java类文件,其内容如下:
public class HelloWrapper {

    static {    
        //注意这里导入的类库名称与「步骤5」中的moduleName匹配  
            System.loadLibrary("HelloJNI");    
    }    

    public native double getSumFromJNI(double num1,double num2);    
}        

1.在菜单栏选择Build->Make Project
此时,选择Make Project查看是不是有错误。若有错误,请查看日志以排除。

2.在需要的地方调用HelloWrapper类

疑问:
上述代码在「模拟器」和「真机」上调用时,结果可能不一致,大家想想,为什么呢?

在iOS设备调用

相对于Android而言,在iOS设备上调用C/C++代码就非常非常非常容易了。大致步骤如下:

1.Xcode中新建一个iOS项目
新建一个名称HelloCPP的iOS项目,先。选择开发语言时,可以选择Objective-C也可以选择Swift,反正都可以调用,反正都可以混合使用,随意啦!

2.将MyClz.h和MyClz.cpp文件拖入项目中
因为Xcode已经有一个main.m文件作为项目的入口,因此请去掉MyClz.cpp文件种的main函数。

3.新建一个Cocoa Class并将其命名为MyClzWrapper
按下快捷键command + N,再弹出的面板中选择新建「Cocoa Class」,并输入名称为:MyClzWrapper。
默认情况下,上述操作会生成一个MyClzWrapper.h和MyClzWrapper.m文件, 修改MyClzWrapper.m文件的后缀名为mm ,使该文件即能编写C/C++代码,也能编写Objective-C代码(也就是传说种的Objective-C++文件)

MyClzWrapper.h文件的内容:

 #import <Foundation/Foundation.h>  

 @interface MyClzWrapper : NSObject

     +(double) getSumFromCPP:(double) number1 :(double) number2;

 @end    

MyClzWrapper.mm文件的内容:


 #import "MyClzWrapper.h"  
 #import "MyClz.h"  

 @implementation MyClzWrapper  

     MyClz* clz = new MyClz();  

     +(double) getSumFromCPP:(double) number1 :(double) number2{  

         return clz->getSum(number1, number2);  
     }  

 @end      

4.在需要的地方调用MyClzWrapper.mm文件

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值