Lua 实验(3) 注册c#方法到lua

来源:互联网 发布:stm32 3轴控制算法 编辑:程序博客网 时间:2024/06/02 03:08

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 调出其中的参数。

0 0
原创粉丝点击