开始本篇文章之前我先为大家简单的介绍一下Android NDK编程的原理, 我们知道Android开发使用JAVA语言来编程它的运行效率要比C/C++低很多,为了让JAVA语言可以调用 C/C++ 这时候NDK就出现了,使用DNK可以很方便的实现 JAVA 与 C/C++之间的互相调用。NDK的工作原理是使用谷歌提供的NDK工具将C/C++的代码编译成 .so文件,最后使用JAVA代码与.so文件之间相互调用。下面我先说一下在Unity中结合Android NDK实现本地数据的共享的原理,如下图所示 ,Unity工程加入NDK后工程大致可分为三个部分 Android(JAVA) 、 C/C++(.so)、Unity(C#)它们之间是可以相互调用的,在之前的文章中我向大家介绍了 Android与Unity之间相互调用的原理,Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)。这种方式只能相互传递String字符串,少量数据传递时可以使用这种方式。如果是大量数据这样就有点限制了,其实我们可以把C/C++的代码做为一个中转站,实现两边的数据引用与共享。

首先在官网中下载NDK最新的安装包,安装包分为三个版本这里我下载使用的是MAC OS版本,最新版本已经到了R8。

OK,我们在Eclipse中创建一个Android工程,在res与src平级文件夹目录下创建一个jni的文件夹。接着在文件夹中创建两个代码文件,分别是C与C++还有一个配置文件Android.mk。

c.c代码一共分为两个方法,先说说方法Java_com_xys_UnityTestActivity_TestAddInt 这个方法是漏给Java代码调用的,jint表示此方法的返回值为整形,数据类型还可以是jlong 、jfloat、jdouble、 jobject、jboolean、jbyte、jchar、jshort,搞程序的一看就应该明白了吧?我就不一一解释了。 方法名中java开头是标准用法,com_xys表示当前程序的包名,UnityTestActivity表示当前类,TestAddInt表示方法名,在Android中就是调用这个方法的,这个方法实现了一个简单的整形相加的操作。在说说第二个方法int addInt(),这个方法是留给Unity中C#语言调用的,它的结构与上面不一样不能在Java代码中调用,同样它也就是实现整形相加的操作。

先是C的文件 c.c

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <string.h>

#include <jni.h>

//Android中java代码调用此方法

jint

Java_com_xys_UnityTestActivity_TestAddInt(JNIEnv*env,jobjectthiz,jinta,jintb)

{

returnaddInt(a,b);

}

//Unity中C#代码调用此方法

intaddInt(inta,intb)

{

returna+b;

}

在看看C++文件,它和C文件的调用原理差不多,不过值得注意的是C++中一定要把需要调用的方法写在extern “C”{ } 中,否则无法调用。

cplus.cpp

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#include

#include

//声明一个类

classMyClass

{

public:

staticfloatadd(floata,floatb)

{

returna+b;

}

};

//外部调用的方法需要写在这里

extern"C"

{

jfloat

Java_com_xys_UnityTestActivity_TestAddFloat(JNIEnv*env,jobjectthiz,jfloata,jfloatb)

{

returnMyClass::add(a,b);

}

floataddFloat(floata,floatb)

{

returnMyClass::add(a,b);

}

}

再看看第三个配置文件,文件中比较重要的两个变量 LOCAL_MODULE表示生成出的.so的名称 LOCAL_SRC_FILES 表示需要编译的文件,如果是多个C/C++文件中间需要使用  \ 隔开。

Android.mk

C#

1

2

3

4

5

6

7

8

9

10

LOCAL_PATH:=$(callmy-dir)

include$(CLEAR_VARS)

LOCAL_MODULE:=xuanyusong

LOCAL_SRC_FILES:=\

c.c\

cplus.cpp

include$(BUILD_SHARED_LIBRARY)

OK ,此时C/C++代码的准备工作就做完了,下面我们学习如何把c.c 与 cplus.cpp 一个C文件与一个C++文件一同打包进.so文件中。首先打开终端,cd到刚刚创建的jni目录下,然后执行一开始下载的DNK开发包中的ndk-build命令,你可以直接在android-ndk-r8中找到ndk-build然后拖拽到终端中即可,如果代码没有错误如图所示表示.so文件编译成功。

再看看当前Android工程的目录结构,libs -> armeabi -> libxuanyusong.so 就是刚刚编译生成的.so文件,xuanyusong.so前面的lib是系统默认添加的,大家不必惊慌。

下面我们编写Java代码,学习如何在java代码中调用C/C++,代码比较简单在OnCreat()方法中分别调用C与C++的方法,并且弹出一个Toast显示在界面中。

UnityTestActivity.java

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

packagecom.xys;

importandroid.os.Bundle;

importandroid.widget.Toast;

importcom.unity3d.player.UnityPlayerActivity;

publicclassUnityTestActivityextendsUnityPlayerActivity

{

@Override

publicvoidonCreate(BundlesavedInstanceState)

{

super.onCreate(savedInstanceState);

//在这里调用.so中的两个方法,并且显示在屏幕中

Toast.makeText(getApplicationContext(),"整形  = "+TestAddInt(1,2)+" 浮点型 = "+TestAddFloat(1.5f,1.1f),

Toast.LENGTH_LONG).show();

}

//声明c.c中的TestAddInt方法

publicnativeintTestAddInt(inta,intb);

//声明cplus.cpp中的TestAddFloat方法

publicnativefloatTestAddFloat(floata,floatb);

static

{

//加载.so文件

System.loadLibrary("xuanyusong");

}

}

好的,我们终于把Android的工程建立完毕。接着我们需要把工程拷贝至Unity的Android插件中, 插件的制作还有谁不会?? 不会的朋友请看之前的文章,这里就不赘述。如下图所示,Android插件已经制作完毕放在Unity中。目录结构如下所示。

编写test.cs脚本,实现通过C#脚本直接访问libxuanyusong.so文件,直接把test.cs挂在摄像机上。使用[DllImport (“xuanyusong”)]来引入.so 的方法, 这里注意的是 一定要把.so文件名的lib 与后缀.so去掉, 最后将数据通过GUI显示在屏幕中。

test.cs

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

usingUnityEngine;

usingSystem.Collections;

usingSystem.Runtime.InteropServices;

publicclasstest:MonoBehaviour{

inti=0;

floatf=0.0f;

//引用C 、C++中的方法

[DllImport("xuanyusong")]

privatestaticexternintaddInt(inta,intb);

[DllImport("xuanyusong")]

privatestaticexternfloataddFloat(floata,floatb);

voidStart()

{

//调用方法中相加函数

i=addInt(1,2);

f=addFloat(1.0f,2.2f);

}

voidOnGUI()

{

//将相加后的信息显示在屏幕中

if(i!=0)

GUILayout.Label(" use  c  ="+i);

if(f!=0.0f)

GUILayout.Label(" use  cplus  ="+f);

}

}

所有的工作已经做完,我们打包编译上真机,首先是在Android中调用.so时 弹出结果的Toast 。

然后是在Unity中调用.so后通过GUI绘制在屏幕中的结果,蛤蛤。Unity给力吧。。

最后雨松MOMO希望和大家一起进步,哇咔咔,啦啦啦,~~~本文下载内容包括 Android工程 与 Unity工程,欢迎大家下载学习。,不早了MOMO祝大家学习愉快并且Good night !

最后编辑:2012-08-09作者:雨松MOMO

专注移动互联网,Unity3D游戏开发

捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

ugui 转轮_Unity3D研究院之Android NDK编译C/C++结合Unity实现本地数据共享(二十八)...相关推荐

  1. Android NDK编译中在libs\armeabi中加入第三方so库文件的方法

    Android NDK编译中在libs\armeabi中加入第三方so库文件的方法 假设要加入库文件的名字为libffmpeg.so文件 1.要在project\jni目录下新建一目录prebuilt ...

  2. android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一

    版权信息:本文为本人原创,欢迎转载,但请著明出处,并保留本版权信息. Android NDK编译脚本编写起来还是是比较简单条理的,然而它的语法和传统的linux GNU Make编译脚本的编写似乎有很 ...

  3. NDK编译php,Android NDK编译常见错误及解决方案

    Android NDK编译常见错误及解决方案 Error 1:$ ndk-build/cygdrive/c/andy/abc/obj/local/armeabi-v7a/objs/abc//hello ...

  4. Android NDK 编译PjSip 2.6 之 搭建PjSip apk开发环境 (三)

    Android NDK 编译PjSip 2.6 之 PjSip编译 (二)中已经把so 和java文件编译出来.可以开始搭建apk的开发环境. 我们导入PjSip的example apk程序,编译生成 ...

  5. android jni不适用ndk,Android NDK编译之undefined reference to 'JNI_CreateJavaVM'

    利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...

  6. android中ndk编译错误,Android NDK编译常见错误及解决方案

    Android NDK编译常见错误及解决方案 Error 1:$ ndk-build/cygdrive/c/andy/abc/obj/local/armeabi-v7a/objs/abc//hello ...

  7. android 编译 sdl,使用android ndk编译SDL2示例错误r14

    我已经测试过在我的ubuntu 16.04机器上构建SDL2源代码(2.0.5)中的示例.使用android ndk编译SDL2示例错误r14 根据https://wiki.libsdl.org/An ...

  8. (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例

    Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21 我要评论 这篇文章主要介绍了Android项 ...

  9. android2.2编译,Android NDK编译Box2D_V2.2

    如果大家有留意的话,就知道现在很流行的 愤怒的小鸟 的物理引擎是使用了Box2D,那么如何将这好东西移植到Android上呢?在网上找了一遍,发现资料还是少得可怜,于是自己研究研究一下,遇到问题就go ...

最新文章

  1. PE学习(三)第三章:PE文件头
  2. APPStore 审核收集
  3. SIFT算法中概念简单解释
  4. 树莓派 php mysql 中文_使用树莓派(raspberry pi)搭建网站(nginx+php+mysql+ddclient)
  5. react和nodejs_如何使用React,TypeScript,NodeJS和MongoDB构建Todo应用
  6. Bootstrap禁用某个按钮组
  7. jackson 复杂对象集合 的几种简单转换
  8. 9277用计算机,【资料】[转]鸿合电子白板学科通用工具使用技巧
  9. 【软件工程】第一次阅读作业
  10. 关于学历与面试的一些看法
  11. 最全的Magisk模块下载
  12. 联想拯救者笔记本摄像头打不开
  13. 中国建设工程造价管理系统 http://zaojiasys.jianshe99.com/cecaopsys/
  14. Docker Nginx配置(docker.io/nginx)
  15. Office Professional Plus 2019 下载安装激活
  16. mov ah,4ch int 21的作用
  17. Spring 马士兵
  18. Facebook取消雅虎的登陆
  19. 帝国双璧--卫青与霍去病
  20. js按钮确认删除提示

热门文章

  1. 【物联网智能网关-05】扫描键盘编程设计
  2. 自定义字体——自带常见图标,以后就省的切图了
  3. 如何在生产环境部署K2的流程
  4. winsock I/O模型
  5. 8088微型计算机pdf,微型计算机原理与接口技术:第3章 8086-8088微处理器及其体系结构.pdf...
  6. centos 静态ip_CentOS 6 静态 IP 配置
  7. html div中心显示,html中心div总是在中间,另外两个是动态的
  8. linux系统开启端口转发,linux如何使用iptables进行本地端口转发
  9. windows失败计算机关闭,win10电脑关机失败怎么办|win10系统正确关机的详细方法
  10. 列名无效怎么解决_电脑win键失效怎么办? 键盘win键无效的解决办法