之前在公司给项目接入过 xLua .接入过程非常傻瓜.
又了解到 Unity 由于历史原因,有各种各样的 lua 接入插件。 slua,xlua,tolua 等等层出不穷。
如果是为了直接在 Unity 项目里使用 Lua,使用现成的插件肯定是最好的选择。如果是为了学习,就需要自己亲手实践一番
之前并不了解 unity 接入 lua 的原理 。
最近通过公司的项目,查阅看官方文档,了解到 Unity 能够使用 C# 代码调用 C++ 写的动态链接库,由此试验了一下从0开始接入 Lua
过程记录如下
#Unity 集成 Lua
文档参考Unity 官方文档 Working in Unity -> Advanced Development -> Plug-ins -> NataivePlug-ins 章节
https://docs.unity3d.com/Manual/NativePlugins.html
[file:///D:/UnityDocumentation_2019/en/Manual/PluginsForDesktop.html](file:///D:/UnityDocumentation_2019/en/Manual/PluginsForDesktop.html)
参考示例
https://github.com/Unity-Technologies/DesktopSamples
Unity 集成动态库
调用外部动态库的代码 ,要借助 InteropServices
因此, C# 中要 using System.Runtime.InteropServices;
这样可以使用 DllImport 标签
只能调用动态库中导出的函数,并且函数必须声明为 extern “C”
在 C# 里声明 C++ 函数,调用时,当作一个正常的 C#函数调用即可
using UnityEngine;
using System.Runtime.InteropServices;
class SomeScript : MonoBehaviour {
#if UNITY_IPHONE
// On __iOS__ plugins are statically linked into
// the executable, so we have to use __Internal as the
// library name.
[DllImport ("__Internal")]
#else
// Other platforms load plugins dynamically, so pass the name
// of the plugin's dynamic library.
[DllImport ("PluginName")]
#endif
private static extern float FooPluginFunction ();
void Awake () {
// Calls the FooPluginFunction inside the plugin
// And prints 5 to the console
print (FooPluginFunction ());
}
}
注意,要给每一个被导出的 C++ 函数加上 DllImport 声明
其中 “PluginName” 是 动态库文件的名字
编写动态库
C# 中,只能调用 C++ 动态库中导出的函数,而不能使用导出的 C++ 类,并且被导出的函数必须声明为 extern “C”
下面例子中,只在 C++ 代码里导出了 函数。希望暴露出来的 LuaMachine 类并没有导出,而是通过函数的形式暴露给 C#
例 Source.h
#pragma once
#ifdef AYY_LUA_BIND_EXPORT
#define AYY_LUA_BIND_API __declspec(dllexport)
#else
#define AYY_LUA_BIND_API __declspec(dllimport)
#endif
extern "C" AYY_LUA_BIND_API void launchLua();
extern "C" AYY_LUA_BIND_API void callLuaFunc();
extern "C" AYY_LUA_BIND_API void executeString(const char* luaCode);
typedef void(__stdcall* CallFunc) (const char* info);
extern "C" AYY_LUA_BIND_API void registerLogHandler(CallFunc func);
void printLog(const char* log);
Source.cpp
#include "../header/Source.h"
#include <stdio.h>
#include "../header/LuaMachine.h"
LuaMachine* machine = nullptr;
CallFunc logHandler = nullptr;
void launchLua()
{
machine = new LuaMachine();
printLog("launchLua\n");
machine->init();
}
void callLuaFunc()
{
if (machine != nullptr)
{
printLog("call lua func,machine NOT null\n");
}
else
{
printLog("call lua func,machine is NULL\n");
}
}
void executeString(const char* luaCode)
{
machine->executeString(luaCode);
}
void registerLogHandler(CallFunc func)
{
logHandler = func;
}
void printLog(const char* log)
{
if (logHandler != nullptr)
{
logHandler(log);
}
{
printf("%s\n",log);
}
}
这里再看一下官方示例的 Plugin.cpp .
官方示例里, _MSC_VER 下 把 EXPORT_API 定义为 __declspec(dllexport)
其他平台 没有使用 宏
#if _MSC_VER // this is defined when compiling with Visual Studio
#define EXPORT_API __declspec(dllexport) // Visual Studio needs annotating exported functions with this
#else
#define EXPORT_API // XCode does not need annotating exported functions, so define is emp