当 Unity 需要使用第三方的库的时候,特别是第三方开发库是使用 C/C++ 来实现的时候,我们就需要针对各个平台编译 Library 来供 Unity 使用。
最近刚刚有过一次封装经验,放在此供大家参考。
这里分三部分来介绍。
Unity 端函数声明
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
public const string PluginName = "liblz4";
#else
#if UNITY_IOS || UNITY_XBOX360
// On iOS and Xbox 360 plugins are statically linked into
// the executable, so we have to use __Internal as the
// library name
public const string PluginName = "__Internal";
#else
// Other platforms load plugins dynamically, so pass the name
// of the plugin's dynamic library.
public const string PluginName = "lz4";
#endif
#endif
[DllImport(PluginName)]
static extern YOUR_RETURN_TYPE YOUR_FUNCTION_NAME(YOUR_PARAMETRES);
注意点:
- Standalone 平台, PluginName 就是动态库或者Bundle的名字;
- IOS 平台一般使用源文件就好,直接用 __Internal;
- Android 平台 PluginName 中不能有 lib 字段,导出的 so 中需要有 lib 字段,例如 liblz4.so。
封装代码
一般是一个头文件加上一个实现文件,头文件中声明函数,实现文件中实现函数。
函数声明格式
#ifdef _WIN32
#ifdef XXX_EXPORT
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API __declspec(dllimport)
#endif
#else
#define EXPORT_API
#endif
extern "C" {
EXPORT_API YOUR_RETURN_TYPE YOUR_FUNCTION_NAME(YOUR_PARAMETERS);
}
注意只有在 Windows 上需要在工程中设置 XXX_EXPORT
预处理变量。
C++ 对象参数怎么表示
在C#层使用 IntPtr 表示,在 C++ 层使用对象指针表示。
例如 Class A 作为函数参数:
// C++
EXPORT_API void Func(A* pA);
// C#
[DllImport(PluginName)]
static extern void Func(IntPtr a);
数组怎么传递
数组传递类似于对象传递,使用指针和一个数组长度字段表示即可。
List/Array 等对象怎么传递
转换成数组
平台库封装
Windows
Windows 使用 VisualStudio 来创建一个 Visual C++ 类库工程来编译,如下图所示。
然后注意导出的平台是 x86/x64 即可,注意需要在工程预处理器中声明
XXX_EXPORT
, vs 提示缺少 stdafx.h 的时候设置配置属性->C/C++->预编译头
为不使用预编译头
即可。
Mac
Mac 平台需要创建一个 Xcode Bundle 工程,如下图所示。
image.pngimage.png
iOS
直接将 .c/.mm 放入工程就好,最为简单。
Android
需要下载 Android SDK 和 Android NDK, 使用 Android Studio 创建一个 Include C++ Support
的工程,然后将我们的 C/C++ 代码加入到工程中。最后使用 Android NDK 编译成 .so。
库文件存放位置
- Windows 放在
Plugins/x86(x64)
目录下; - Mac 直接放在
Plugins
目录下; - iOS 放在
Plugins/iOS
目录下; - Android 放在
Plugins/Android/libs/armeabi-v7a
目录下。
注意点
- 如果修改了本地插件,需要将 dll 或者 bundle 覆盖了之后重启 Unity, 不然还是会使用老的 Native Plugin;
- 调试起来比较麻烦,建议使用文件的方式进行日志输出来进行比较。
网友评论