编写跨平台代码可能很困难, 但是通过一些方法可以更易于开发与维护. 本教程列举了 Defold 与跨平台原生代码共同工作的 API 和方法.
在 Defold 引擎中我们很少使用 C++ 代码. 事实上, 大多数是 C-like 代码. 除了少数容器类外, 我们去掉了模板, 因为模板会增加编译时间和包体大小.
Defold 源码使用默认 C++ 版本编译.
我们不用最新的 C++ 版本及特性. 主要因为默认版本对于游戏引擎足够用了. 追寻最新 C++ 版本特性相当耗费时间.
这也有助于向扩展开发者提供稳定 ABI. 而且使用最新 C++ 特性的话很可能会在不同平台上造成编译问题.
Defold 引擎不支持 STL 代码, 除了某些算法和数学库 (std::sort, std::upper_bound 等), 但是你的扩展里可以使用 STL.
再次注意 ABI 的不兼容性可能使你使用其他扩展或者第三方库造成困难.
去掉 (重模板化的) STL 库, 还能减少编译时间, 更重要的是, 减小应用体积.
在 Defold 引擎中, 我们使用 const char*
代替了 std::string
.
std::string
使得 C++ 不同版本混合编译造成困难: 原因是 ABI 不匹配.
所以我们选择使用 const char*
及相关工具函数代替.
本地函数尽量使用 static
关键字定义. 这样便于编译器优化, 提高性能减小应用体积.
当我们选用第三方库时 (不管由什么语言编写), 至少需要考虑这些事情:
确定你能访问你的依赖库. 比如说在 GitHub 上托管的库, 随时可能被移除, 突然改变开发方向或者改变拥有者维护者. 如果你fork了这个库就能减少这些变化带来的损失.
库代码是直接注入你的游戏中的, 所以需要保证它在满足你的要求的前提下不会在后台做什么小动作!
当你创建扩展, 开发和维护时是有些技巧的.
应该只有一个 Lua api, 只有一个实现方法. 这样有助于在所有平台上保持一致的表现.
如果某平台不支持这个扩展, 建议不要注册 Lua 模块. 这样就可以通过检查非 nil 来判断对扩展的支持性:
if myextension ~= nil then
myextension.do_something()
end
这是我们开发扩展使用的常用结构.
/root
/input
/main -- 示例项目根目录
/...
/myextension -- 扩展根目录
ext.manifest
/include -- 其他扩展使用的外部包含
/libs
/<platform> -- 各个平台使用的外部包含
/src
myextension.cpp -- 扩展的 Lua api 及其生命周期函数
还包含 Lua api 功能的通用实现方法.
myextension_private.h -- 每个平台需要实现的内部 api (也就是 `myextension_Init` 之类的功能)
myextension.mm -- 如果需要调用 iOS/macOS 原生功能. 就要为 iOS/macOS 实现 `myextension_Init` 之类的功能
myextension_android.cpp -- 如果需要调用 Android 的JNI. 就要为 Android 实现 `myextension_Init` 之类的功能
/java
/<platform> -- Android 需要的java文件
/res -- 平台需要的资源文件
/external
README.md -- 扩展相关编译打包的说明/脚本
/bundleres -- 需要打包的资源 (参见 game.project 以及 [bundle_resources 设置](/zh/manuals/project-settings/#Project))
/<platform>
game.project
game.appmanifest -- 其他应用设置
注意 myextension.mm
和 myextension_android.cpp
只在调用平台特定原生功能时使用.
在某些地方, 需要针对架构平台命名文件夹, 以便应用编译/打包时使用正确的文件. 结构是这样的:
<architecture>-<platform>
目前支持的有:
arm64-ios, armv7-ios, x86_64-ios, arm64-android, armv7-android, x86_64-linux, x86_64-osx, x86_64-win32, x86-win32
比如, 这么放置平台相关库:
/libs
/arm64-ios
/libFoo.a
/arm64-android
/libFoo.a
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB