欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

原生實(shí)現(xiàn)C#與Lua相互調(diào)用方法(Unity3D可用)

 更新時間:2022年04月17日 16:06:12   作者:爆走de蘿卜  
Lua是一種很好的擴(kuò)展性語言,Lua解釋器被設(shè)計(jì)成一個很容易嵌入到宿主程序的庫,下面這篇文章主要給大家介紹了關(guān)于原生實(shí)現(xiàn)C#與Lua相互調(diào)用方法,Unity3D可用的相關(guān)資料,需要的朋友可以參考下

引言

本篇簡單介紹如何在C#中執(zhí)行Lua腳本,傳遞數(shù)據(jù)到Lua中使用,以及Lua中調(diào)用C#導(dǎo)出的方法等。在Unity中開發(fā)測試,并打IL2CPP的Android包在模擬器上運(yùn)行通過。Lua版本使用的是Lua5.1.5。

一、編譯Lua動態(tài)鏈接庫

1. 編譯Windows下使用的DLL文件

使用VS2015創(chuàng)建一個空的動態(tài)鏈接庫項(xiàng)目,刪除里面默認(rèn)創(chuàng)建的幾個文件(如果想自定義拓展可用保留),然后把Lua的源碼拷貝進(jìn)來,添加到項(xiàng)目工程中,編譯宏需要配置LUA_BUILD_AS_DLL和_CRT_SECURE_NO_WARNINGS。然后就可以編譯x86和x64的DLL動態(tài)庫,整體步驟簡單易操作。

2. 編譯Android下使用的SO文件

通過NDK編譯Android需要的so動態(tài)庫,因此需要手寫Application.mk和Android.mk兩個mk文件,下面是我使用的兩個文件的內(nèi)容,創(chuàng)建放在上面VS的工程里面即可,路徑是在lua源碼src的上一層目錄。

# Application.mk
APP_PLATFORM = android-23
APP_ABI := armeabi-v7a arm64-v8a
APP_STL := stlport_shared
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
MY_FILES_PATH  :=  $(LOCAL_PATH)/src
MY_FILES_SUFFIX := %.c
MY_UN_INCLUDE := %lua.c %luac.c
# 遞歸遍歷目錄下的所有的文件
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
# 獲取相應(yīng)的源文件
MY_ALL_FILES := $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*.*) )
MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(MY_ALL_FILES))
MY_SRC_LIST  := $(filter-out $(MY_UN_INCLUDE),$(MY_SRC_LIST))
MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)
LOCAL_SRC_FILES = $(MY_SRC_LIST)
#打印編譯信息
$(warning 'src_list='$(LOCAL_SRC_FILES))
LOCAL_MODULE    := CSharpLua
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLGAS)
include $(BUILD_SHARED_LIBRARY)

將上面的mk文件放置完成后,打開CMD命令行,執(zhí)行ndk編譯。由于并不是在Android的jni項(xiàng)目目錄,因此執(zhí)行命令會有所不同,可以使用下面的命令執(zhí)行生成,等待ndk執(zhí)行完成后就生成了需要的so庫。

ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk

二、編寫C#使用的API

1. 動態(tài)鏈接庫在Unity中的存放位置。

在Unity項(xiàng)目Assets目錄里面創(chuàng)建Plugins目錄,用于存放不同平臺的DLL庫。Windows需要的DLL存放的目錄為Assets/Plugins/x86和Assets/Plugins/x86_64;Android需要的SO文件存放的目錄為Assets/Android/[libs/arm64-v8a]括號里面的目錄其實(shí)就是上面NDK編譯后生成的路徑。

2. 編寫C#的API[LuaDll.cs]

大部分的動態(tài)庫中的接口直接使用以下這種方式即可使用,使用IntPtr來表示lua_State*對象,傳入?yún)?shù)char*可用使用byte[]或者string,但是會有一點(diǎn)點(diǎn)區(qū)別。

[DllImport("CSharpLua", EntryPoint = "luaL_newstate")]
public static extern IntPtr luaL_newstate();
[DllImport("CSharpLua", EntryPoint = "luaL_openlibs")]
public static extern void luaL_openlibs(IntPtr L);
[DllImport("CSharpLua", EntryPoint = "luaL_loadbuffer")]
public static extern int luaL_loadbuffer(IntPtr L, byte[] buff, uint size, string name);
[DllImport("CSharpLua", EntryPoint = "lua_call")]
public static extern void lua_call(IntPtr L, int nargs, int nresults);
[DllImport("CSharpLua", EntryPoint = "lua_pcall")]
public static extern int lua_pcall(IntPtr L, int nargs, int nresults, int errfunc); 

3.需要注意的幾個地方

1. 返回char*時,不可直接使用string替換,否則調(diào)用會導(dǎo)致崩潰,因此需要像下面代碼展示的那樣進(jìn)行一下轉(zhuǎn)換才可以使用。

[DllImport("CSharpLua", EntryPoint = "lua_tolstring")]
private static extern IntPtr _lua_tolstring(IntPtr L, int idx, ref uint size);
public static string lua_tolstring(IntPtr L, int idx, ref uint size)
{
    IntPtr buffer = _lua_tolstring(L, idx, ref size);
    return Marshal.PtrToStringAnsi(buffer);
}

2. C#函數(shù)傳遞給Lua使用時,需要使用delegate委托類型。

public delegate int LuaFunction(IntPtr L);
[DllImport("CSharpLua", EntryPoint = "lua_pushcclosure")]
public static extern void lua_pushcclosure(IntPtr L, LuaFunction func, int idx);
public static void lua_pushcfunction(IntPtr L, LuaFunction func)
{
   lua_pushcclosure(L, func, 0);
}

3. 在lua源碼中定義的宏代碼是無法使用的,會提示找不到,需要在C#中手動實(shí)現(xiàn),例如下面展示的2個宏。

#define lua_setglobal(L,s)  lua_setfield(L, LUA_GLOBALSINDEX, (s))
#define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, (s))
[DllImport("CSharpLua", EntryPoint = "lua_getfield")]
public static extern void lua_getfield(IntPtr L, int idx, string s);
public static void lua_getglobal(IntPtr L, string s)
{
   lua_getfield(L, LUA_GLOBALSINDEX, s);
}
[DllImport("CSharpLua", EntryPoint = "lua_setfield")]
public static extern void lua_setfield(IntPtr L, int idx, string s);
public static void lua_setglobal(IntPtr L, string s)
{
   lua_setfield(L, LUA_GLOBALSINDEX, s);
}

4. 如需要將C#的類實(shí)例對象即userdata傳遞給lua,需要在C#中轉(zhuǎn)換成IntPtr后傳遞,Lua返回的則需要通過IntPtr轉(zhuǎn)換回C#的實(shí)例對象。

[DllImport("CSharpLua", EntryPoint = "lua_pushlightuserdata")]
public static extern void _lua_pushlightuserdata(IntPtr L, IntPtr p);
public static void lua_pushlightuserdata<T>(IntPtr L, T p)
{
    IntPtr obj = Marshal.GetIUnknownForObject(p);
    _lua_pushlightuserdata(L, obj);
}
[DllImport("CSharpLua", EntryPoint = "lua_touserdata")]
public static extern IntPtr _lua_touserdata(IntPtr L, int idx);
public static T lua_touserdata<T>(IntPtr L, int idx)
{
   IntPtr p = _lua_touserdata(L, idx);
   return (T)Marshal.GetObjectForIUnknown(p);
}

三、C#與Lua的相互調(diào)用舉例

1. C#中創(chuàng)建Lua環(huán)境

IntPtr L = LuaDll.luaL_newstate();
LuaDll.luaL_openlibs(L);

2. 加載Lua代碼并執(zhí)行,調(diào)用Lua的函數(shù)及向Lua傳遞參數(shù)。

var data = Resources.Load<TextAsset>(lua_file);
int rc = LuaDll.luaL_loadbuffer(L, data.bytes, (uint)data.bytes.Length, lua_file);
rc = LuaDll.lua_pcall(L, 0, 0, 0)
LuaDll.lua_getglobal(L, "main");
// 傳遞參數(shù)
LuaDll.lua_pushinteger(L, 3333);
LuaDll.lua_pushnumber(L, 3.3);
// 執(zhí)行main方法
int i = LuaDll.lua_pcall(L, 2, 0, 0);

3. 將C#函數(shù)提供給Lua使用,需要使用靜態(tài)方法參考上面LuaFunction的定義。

LuaDll.lua_pushcfunction(L, LuaPrint);
LuaDll.lua_setglobal(L, "print");
[MonoPInvokeCallback]   // 這個主要是在Android上需要。
static int LuaPrint(IntPtr L)
{
  Debug.Log(".....");
  return 0;
}

4. Lua代碼調(diào)用C#方法并提供回調(diào),由C#函數(shù)調(diào)用。

static int FindAndBind(IntPtr L)
{
   GameObject go = LuaDll.lua_touserdata<GameObject>(L, 1);
   string path = LuaDll.lua_tostring(L, 2);
   // 這里將lua的函數(shù)放到LUA_REGISTRYINDEX上
   int idx = LuaDll.luaL_refEx(L);
   Transform t = go.transform.Find(path);
   Button btn = t.GetComponent<Button>();
   btn.onClick.AddListener(delegate() {
     // 從LUA_REGISTRYINDEX棧獲取lua的函數(shù)進(jìn)行執(zhí)行。
     LuaDll.lua_rawgeti(L, LuaDll.LUA_REGISTRYINDEX, idx);
     LuaDll.lua_pcall(L, 0, 0, 0);
   });
   return 0;
}

四、總結(jié)

總體來說交互調(diào)用還是比較的簡單方便,跟使用C/C++與Lua交互差不多。我僅僅簡單使用Lua源碼進(jìn)行編譯動態(tài)庫使用,可以方便的替換各個版本的lua進(jìn)行使用。C#導(dǎo)出方法給Lua使用也相對簡單,但是Unity中使用Lua的時候,不可能每個類例如GameObject、Transform等都手動寫導(dǎo)出的代碼給Lua使用。這塊就可以去看tolua、xlua的實(shí)現(xiàn),需要考慮很多東西。

到此這篇關(guān)于原生實(shí)現(xiàn)C#與Lua相互調(diào)用方法的文章就介紹到這了,更多相關(guān)C#與Lua相互調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • c#中LINQ的基本用法(三)

    c#中LINQ的基本用法(三)

    這篇文章介紹了c#中LINQ的基本用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下的相關(guān)資料
    2022-04-04
  • C#基于Socket實(shí)現(xiàn)多人聊天功能

    C#基于Socket實(shí)現(xiàn)多人聊天功能

    這篇文章主要為大家詳細(xì)介紹了C#基于Socket實(shí)現(xiàn)多人聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C# SQLite執(zhí)行效率的優(yōu)化教程

    C# SQLite執(zhí)行效率的優(yōu)化教程

    這篇文章主要給大家介紹了關(guān)于C# SQLite執(zhí)行效率優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C# SQLite具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • 淺談關(guān)于C#的垃圾回收機(jī)制

    淺談關(guān)于C#的垃圾回收機(jī)制

    淺談關(guān)于C#的垃圾回收機(jī)制,需要的朋友可以參考一下
    2013-03-03
  • c#判斷操作系統(tǒng)位數(shù)的示例分享

    c#判斷操作系統(tǒng)位數(shù)的示例分享

    這篇文章主要介紹了c#判斷操作系統(tǒng)位數(shù)的示例,在.net 4.5中,判斷操作系統(tǒng)不用再寫方法去判斷了,有直接可以利用的屬性了哦
    2014-01-01
  • C#集合之鏈表的用法

    C#集合之鏈表的用法

    這篇文章介紹了C#集合之鏈表的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • c#遍歷System.drawing.Color下面的所有顏色以及名稱以查看

    c#遍歷System.drawing.Color下面的所有顏色以及名稱以查看

    c#遍歷System.drawing.Color下面的所有顏色以及名稱以查看,需要的朋友可以參考一下
    2013-02-02
  • C#使用iTextSharp添加PDF水印

    C#使用iTextSharp添加PDF水印

    這篇文章主要為大家詳細(xì)介紹了C#使用iTextSharp添加PDF水印的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 理解C#編程中的靜態(tài)類和靜態(tài)成員以及密封類

    理解C#編程中的靜態(tài)類和靜態(tài)成員以及密封類

    這篇文章主要介紹了理解C#編程中的靜態(tài)類和靜態(tài)成員以及密封類,注意類成員的相關(guān)訪問限制和類的繼承問題,需要的朋友可以參考下
    2016-01-01
  • C#驗(yàn)證碼問題的快速解決方法

    C#驗(yàn)證碼問題的快速解決方法

    下面小編就為大家?guī)硪黄狢#驗(yàn)證碼問題的快速解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07

最新評論