找回密码
 立即注册
查看: 3463|回复: 83

[手机] Android NDK编译C/C++结合Unity实现本地数据共享(转)

[复制链接]
发表于 2012-12-28 20:55 | 显示全部楼层 |阅读模式
资源信息 Tutorial Information
教程名称: Android NDK编译C/C++结合Unity实现本地数据共享(转)(发帖教程)
适用引擎:   (适用引擎,为空默认为Unity)
教程语种: 中文
教程等级: 1
教程格式: 图文(请用IE9以上浏览器访问本版块)
教程作者: 转载自互联网 (如有问题请短消息联系作者或发表回复)
下载地址: (兑换积分)
点击查看原图
美丽分割线
本帖最后由 U侠 于 2012-12-28 20:57 编辑

开始本篇文章之前我先为大家简单的介绍一下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。

下载地址:http://developer.android.com/sdk/ndk/index.html


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

#include <string.h> #include <jni.h> //Android中java代码调用此方法 jint Java_com_xys_UnityTestActivity_TestAddInt( JNIEnv* env, jobject thiz ,jint a,jint b) { return addInt(a,b); } //Unity中C#代码调用此方法 int addInt(int a, int b) { return a + b; }

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

cplus.cpp

#include <string.h> #include <jni.h> //声明一个类 class MyClass { public: static float add(float a, float b) { return a + b; } }; //外部调用的方法需要写在这里 extern "C" { jfloat Java_com_xys_UnityTestActivity_TestAddFloat( JNIEnv* env, jobject thiz ,jfloat a,jfloat b) { return MyClass::add(a,b); } float addFloat(float a,float b) { return MyClass::add(a,b); } }

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

Android.mk

LOCAL_PATH := $(call my-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

package com.xys; import android.os.Bundle; import android.widget.Toast; import com.unity3d.player.UnityPlayerActivity; public class UnityTestActivity extends UnityPlayerActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //在这里调用.so中的两个方法,并且显示在屏幕中 Toast.makeText(getApplicationContext(), "整形 = " + TestAddInt(1,2)+" 浮点型 = " + TestAddFloat(1.5f, 1.1f), Toast.LENGTH_LONG).show(); } //声明c.c中的TestAddInt方法 public native int TestAddInt(int a, int b); //声明cplus.cpp中的TestAddFloat方法 public native float TestAddFloat(float a, float b); 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

using UnityEngine; using System.Collections; using System.Runtime.InteropServices; public class test : MonoBehaviour { int i = 0 ; float f = 0.0f; //引用C 、C++中的方法 [DllImport ("xuanyusong")] private static extern int addInt(int a,int b); [DllImport ("xuanyusong")] private static extern float addFloat(float a,float b);         void Start () { //调用方法中相加函数 i = addInt (1,2); f = addFloat (1.0f,2.2f); } void OnGUI() { //将相加后的信息显示在屏幕中 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 !

下载地址: http://115.com/file/c28d67s5#android-ndk.zip

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2013-1-22 17:47 | 显示全部楼层
第二遍看了 但还是看不懂
发表于 2013-9-19 10:53 | 显示全部楼层
感谢楼主的无私分享!{:5_376:}{:5_412:}
发表于 2014-5-5 21:40 | 显示全部楼层
{:5_401:}看不懂~~~
发表于 2017-3-3 11:45 | 显示全部楼层
顶顶多好
发表于 2017-3-3 11:15 | 显示全部楼层
难得一见的好帖
发表于 2017-3-3 11:04 | 显示全部楼层
说的非常好
发表于 2017-3-3 11:38 | 显示全部楼层
很好哦
发表于 2017-3-3 11:04 | 显示全部楼层
不错不错
发表于 2017-4-20 22:16 | 显示全部楼层
很不错
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-3-29 17:58 , Processed in 0.103070 second(s), 31 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表