1.首先在C的工程中 加入一些接口方法
#define EXPORTBUILD
//加载头文件
#include "LuaInterface.h"
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "luaconf.h"
_DLLExport void LI_doString(lua_State *L , char* chunk)
{
luaL_dostring(L, chunk);
}
_DLLExport double LI_tonumber(lua_State *L, int idx)
{
return lua_tonumberx(L,idx,NULL);
}
_DLLExport void LI_register(lua_State *L, const char *str , lua_CFunction fn)
{
lua_register(L,str,fn);
}
因为Lua只提供了一些基本的方法导出到dll,以上的一些方法只定义了宏,所以将这些方法定义好。
2. 然后将lua工程还有上面的文件导出为DLL放入U3D plugin下。
3. U3D下,新建Test.cs
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System;
public delegate int LuaCSFunction(IntPtr luaState);
[AttributeUsage(AttributeTargets.Method)]
public sealed class MonoPInvokeCallbackAttribute : Attribute
{
public MonoPInvokeCallbackAttribute(Type type)
{
}
}
public class Test : MonoBehaviour {
const string dllName = "lualib";
[DllImport (dllName)]
public static extern int MyLuaDoString(string abc);
[DllImport(dllName)]
public static extern BITMAP TestMap(int x, int y);
[DllImport(dllName)]
public static extern IntPtr DllluaL_newstate();
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void DllluaL_openlibs(IntPtr L);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void DllluaL_dostring(IntPtr luaState , string abc);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void Dlllua_close(IntPtr luaState);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern double Dlllua_tonumber(IntPtr luaState, int idx);
[DllImport(dllName)]
public static extern IntPtr luaL_newstate();
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void luaL_openlibs(IntPtr L);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern int luaL_loadstring(IntPtr luaState, string chunk);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern int lua_pcall(IntPtr luaState, int nArgs, int nResults, int errfunc);
[DllImport(dllName)]
public static extern void my_doString(IntPtr luaState, string chunk);
[DllImport(dllName)]
public static extern void LI_doString(IntPtr luaState, string chunk);
[DllImport(dllName)]
public static extern double LI_tonumber(IntPtr luaState, int idx);
[DllImport(dllName)]
public static extern double LI_register(IntPtr luaState, string str , IntPtr fn);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void lua_close(IntPtr luaState);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern double lua_tonumber(IntPtr luaState, int idx);
public void RegFunction(IntPtr luaState, string name, LuaCSFunction func)
{
IntPtr fn = Marshal.GetFunctionPointerForDelegate(func);
LI_register(luaState, name, fn);
}
public int TestAddInCS(int a,int b)
{
Debug.LogWarning("----"+a);
return a+b;
}
void Awake()
{
/*int aa = MyLuaDoString("print(1+2);return 4;");
Debug.LogWarning("-----");
Debug.LogWarning("-----"+aa);
BITMAP tm = TestMap(2, 3);
IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(tm));
Marshal.StructureToPtr(tm, intPtr, false);*/
IntPtr ptr2 = luaL_newstate();
luaL_openlibs(ptr2);
//luaL_loadstring(ptr2, "hellO");
Debug.LogWarning("-----");
RegFunction(ptr2, "UDebug", UDebug);
LI_doString(ptr2, "UDebug();print(1+2);return 100;");
double res = LI_tonumber(ptr2, -1);
Debug.LogWarning("-----" + res);
lua_close(ptr2);
}
void Update ()
{
}
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
public static int UDebug(IntPtr L)
{
Debug.LogWarning("hello");
return 0;
}
}
首先,要注册方法到Lua,那么就要用到
public static extern double LI_register(IntPtr luaState, string str , IntPtr fn);
这个方法,
在lua dll工程中,对应的是
_DLLExport void LI_register(lua_State *L, const char *str , lua_CFunction fn)
这个方法,其中c工程中如果是类什么的,我们都用指针去对应他。包括之前的lua_State 也是如此。
而在C#端,传方法要用的是委托的形式,所以用
public void RegFunction(IntPtr luaState, string name, LuaCSFunction func)
这个方法进行转换委托->指针 。
然后调用LI_register即可。
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] 只是一个说明,说明这个方法是作为LuaCSFunction 委托使用的。其实不要这个说明也没关系。
整个流程就是 C# 委托->C# IntPtr指针 (非委托形式) -> lua dll 指针
4. 最后得出结果 (hello 是c# 这边的方法打印出来的,lua调用这个方法。)
5. 如果需要传递参数,LUA有个好就是参数也会绑定到类实例上。
修改UDebug如下;
public static int UDebug(IntPtr L)
{
Debug.LogWarning("---------In UDebug");
double res = LI_tonumber(L, 1);
Debug.LogWarning(string.Format("-----:{0}" ,res));
return 0;
}
参数是存在了luastate 对象里面的。通过栈的形式,所以需要L_tonumber 调出其中的参数。