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

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

主要工作原理

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

需要调用的C++代码

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

MyClz.h文件

#include <iostream>

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.hMyClz.cpp文件放入其中。
  7. {project_home}/app/src/main/jni目录中新增MyClz-JNI.cpp文件
    因为之前编写的MyClz.hMyClz.cpp文件不符合JNI的规范(客户提供的cpp文件很少会有符合JNI规范的),因此我们需要编写一个**符合JNI规范**的cpp文件。
    到这一步时,{project_home}/app/src/main/jni目录中应该包含了MyClz.hMyClz.cppMyClz-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相关文档,这里就不在详述。

  1. 编写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.hMyClz.cpp文件拖入项目中
    因为Xcode已经有一个main.m文件作为项目的入口,因此请去掉MyClz.cpp文件种的main函数
  3. 新建一个Cocoa Class并将其命名为MyClzWrapper
    按下快捷键command + N,再弹出的面板中选择新建「Cocoa Class」,并输入名称为:MyClzWrapper。
    默认情况下,上述操作会生成一个MyClzWrapper.hMyClzWrapper.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文件

文章源码下载

请异步 git@oschina https://git.oschina.net/baratsemet/CPP_Andoird_iOS

时间: 2024-08-28 13:26:09

在Android和iOS设备上调用C++代码的相关文章

如何在Android和iOS设备上录制游戏?

内容简介 如何在Android和iOS设备上录制游戏? 如何在Android和iOS设备上录制游戏? Xbox One,PS4,Windows 10等都集成了游戏录制功能,而且可以把录制的视频分享到网上. 现在,Android和iOS设备也可以实现游戏录制了. 怎么做呢?我们分为Android和iOS平台来介绍. Android平台 首先下载安装一个App,叫做<Google Play Games>. 运行此App,在菜单中点击<My Game>(英语<我的游戏>的意思

XPhone 用来管理Android 和IOS 设备的COM库

花了好长时间,终于出来了第一个测试版本的SDK了,功能现在还不完整,而且肯定有非常多的BUG存在,各位童鞋们,有喜欢研究的可以帮忙测试,并且把demo 完善一下. XPhone 是一套COM 的C++库,这套库用来管理Android 和IOS 设备,提供了非常多接口用来操作设备,使用者只需要简单的调用一些接口就可以做出一个手机助手,使用这套库也许只需要一天时间就可以做出一个雏形.可以在demo 上继续完善功能. SVN地址:   svn://www.oksvn.com/XPhone QQ群: 3

Unity在Android和iOS中如何调用Native API

本文主要是对unity中如何在Android和iOS中调用Native API进行介绍. 首先unity支持在C#中调用C++ dll,这样可以在Android和iOS中提供C++接口在unity中调用.利用这一特性,可以扩展unity的功能.例如集成和调用第三方库.同时为了满足对unity接口的一致性,可以考虑在android和iOS上提供相同的接口供C#调用. 这里列举以下两个例子. 1. 1. 以弹出一个覆盖部分屏幕的webview为例来说明如何从C#调用Native接口. 2. 2. 简

使IFRAME在iOS设备上支持滚动

原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚 很长时间以来, iOS设备上Safari中超出边界的元素将不能滚动,处理这种问题对开发人员来说一直是种折磨. 对原文作者的博客来说,这特别让人无奈,因为demo程序都是在沙箱IFRAMEs中运行的,这是为了不影响博客网站的AJAX页面加载策略.  通过一些研究发现,只要设置两个CSS属性,以及加上一个元素,这个问题就解决了. Here we go!(译者注

在ios设备上调试

ZJAppleID2014 1.创建开发者证书 每个开发者人员一次仅允许使用一个开发者证书,证书的管理可以登录 ios开发中心的配置门户网站(https://developer.apple.com/devcenter/ios/manage/overview/index.action) 登录该网站时,需要苹果的ios开发者帐号,登录成功后的界面如下: 点击IOS Apps下的Certificates(证书)导航菜单,得到的证书管理界面如下图所示,在此处下载证书和删除证书. 创建证书的过程分成两部:

怎样将游戏从Unity导到iOS设备上

当我开始开发自己的iOS游戏时,我会考虑的第一件事便是如何将其导出到设备中,如此有效地测试我的游戏.最初,该过程看似很长且复杂,我所遇到的主要问题是,尽管存在许多资源,但是它们并非完全来自同样的地方,所以我不得不通过各种教程将其组合并匹配在一起.所以我决定通过本文一步步地总结这一过程.这是我到目前为止所遵循的一些方式;希望这也能够带给处于同样开发阶段的人更多帮助. 1.获得unity和iOS导出器 如果你还未这么做,你首先需要在官网下载最新版本的Unity.已经出现了2个版本,分别是免费版(ht

不通过AppStore,在iOS设备上直接安装应用程序的原理

本文转载至  http://mobile.51cto.com/hot-439095.htm 通过itms-services协议,可以通过safari浏览器直接在iOS设备上安装应用程序.利用这种方式,只要在内网布置一个服务器,测试人员只需要通过测试设备的safari浏览器访问特定的url既可以实现安装,然后测试了. AD:WOT2015 互联网运维与开发者大会 热销抢票 通过itms-services协议,可以通过safari浏览器直接在iOS设备上安装应用程序.利用这种方式,只要在内网布置一个

【转】使IFRAME在iOS设备上支持滚动

原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚 很长时间以来, iOS设备上Safari中超出边界的元素将不能滚动,处理这种问题对开发人员来说一直是种折磨. 对原文作者的博客来说,这特别让人无奈,因为demo程序都是在沙箱IFRAMEs中运行的,这是为了不影响博客网站的AJAX页面加载策略.  通过一些研究发现,只要设置两个CSS属性,以及加上一个元素,这个问题就解决了. Here we go!(译者注

iOS企业版app部署到自己服务器,不通过AppStore,在iOS设备上直接安装应用程序

iOS企业版app部署到服务器 .正对ios升级得ios7 以后,plist文件必须放到 https得服务器上了,http不可以用了 .plist参照模板如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyLis