Unity使用第三方C语言库思路小结

目标

Unity开发中可能会用到一些强大的第三方库,而基于跨平台的库多是使用C/C++开发的,为了方便在 Unity中使用,我们想将C库做成一个插件,暴露几个接口函数在Unity中使用C#直接调用。关键要做的是将源代码库编译成一个动态库,例如windows下的dll等,然后是实现C#与C的一个函数通信。

PC平台库

使用VS可以直接编译出dll库,即将已有的依赖的源码库的输出看做动态库,创建一个动态库工程引用这些动态库,编写一个头文件进行封装,解决方案输出一个dll供unity调用。

但是这种dll只能在unity发布的.exe包PC平台上运行,只有打PC包时该dll才会build到包中,在安卓、iOS等平台移动平台上是无法使用的。其中安卓系统是基于linux的,需要编译.so包才能在安卓上跑。

注意1:在出PC包时,如果使用了这种第三方dll库,要看一下该dll库依赖了那些系统的dll库,一同放到exe的所在目录下,否则在其他windows电脑上找不到所依赖的系统库会调用dll失败无法正常运行。

例如下面打出的PC包,使用了下面自己编译的一个dll库,就需要看一下那个sdggnugo.dll依赖那些系统库,一同放入包中:
这里写图片描述
这里写图片描述

可以使用Dependency Walker等工具查看dll的依赖库情况:
这里写图片描述
这里依赖MSVCR120D.DLL和KEREL32.DLL两个系统库,都可以在本地C盘system32目录中找到,复制到包中即可:
这里写图片描述
这样即使别人的电脑确实这两个dll系统库也可以正常运行该软件。

注意2: 上面所说的C/C++库制作的dll库是只能在windows上使用的,但如果是C#写的库做成的dll,可以在各平台上使用的,直接将这种dll库放到unity的Plugins根目录下即可。

发布到安卓平台

要想将第三方C库应用到安卓设备上,就需要编译.so库了,而不是dll,dll是windows平台上的动态库,而so是linux平台上的动态库。将C库做成so可以在linux系统中编译,也可以在widnows平台上交叉编译。

在windows平台交叉编译so库,对于比较复杂的库需要使用cmake语法将工程组织起来,然后使用ndk进行编译即可得到相应的so库。

注意1: ndk的版本不宜过新;

注意2:库中C语言(.c文件)的函数是可以直接在unity运行时调用的,如果是C++或者是用C++封装C库,则需要使用extern “C”包一下,具体见unity文档中关于native plugin的介绍。

C++封装C库暴露接口示例

.h

#if defined (EXPORTBUILD)  
# define _DLLExport __declspec (dllexport)  
# else  
# define _DLLExport __declspec (dllimport)  
#endif  

extern "C"{
#include "gnugo.h"
}
extern "C" int _DLLExport Add(int x,int y);

.cpp

#define  EXPORTBUILD  
#include "xx.h"

int _DLLExport Add(int x, int y){
    return x + y;
}

假设打出的库文件为’myadd.dll’,在unity中调用:

using System.Runtime.InteropServices;
// 运行时加载动态库
[DllImport("myadd")]
public static extern int Add(int x, int y);

void Start(){
int result = Add(1,2); // 调用
}

直接暴露C函数

直接新建一个.c文件,里面直接编写想暴露的函数,将该c文件一同编译到库中即可:

xx.c

// 可以include第三方库的头文件
int Add(int x,int y){
    // 可以在这里调用第三方库的函数
    return x+y;
}

在unity中调用的方法一样:

using System.Runtime.InteropServices;
// 运行时加载动态库
[DllImport("myadd")]
private static extern int Add(int x, int y);

void Start(){
int result = Add(1,2); // 调用
}

总结

  • 制作windows平台的C语言动态库直接在VS中打出dll库拖入unityPlugins目录即可;
  • 要打包到安卓平台,则需要编译.so库;

猜你喜欢

转载自blog.csdn.net/cordova/article/details/78208876