亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

C語言與Lua之間的相互調用詳解

2020-01-26 13:48:36
字體:
來源:轉載
供稿:網友

前言

第一次接觸Lua是因為Unity游戲中需要熱更,但是一直沒搞懂Lua是怎么嵌入到別的語言中執行的,如何互相調用的。

lua是擴展性非常良好的語言,雖然核心非常精簡,但是用戶可以依靠lua庫來實現大部分工作。除此之外,lua還可以通過與C函數相互調用來擴展程序功能。在C中嵌入lua腳本既可以讓用戶在不重新編譯代碼的情況下修改lua代碼更新程序,也可以給用戶提供一個自由定制的接口,這種方法遵循了機制與策略分離的原則。在lua中調用C函數可以提高程序的運行效率。lua與C的相互調用在工程中相當實用,本文就來講解lua與C相互調用的方法。這次打算好好了解一下C跟lua是如何交互的

那么如何使用Lua語言?

lua是c語言編寫的,而且開源??梢栽趆ttps://www.lua.org官網上下載Lua的源碼,然后嘗試編譯它!是不是跟我一樣好激動,一直用集成環境,寫上層語言,今天居然要碰編譯了??!~ 可怎么編譯呢?

讓我們召喚出編譯神器:gcc!【GNU編譯器套件(GNU Compiler Collection)包括C、C++、Objective-C、Fortran、Java、Ada和Go語言的前端,也包括了這些語言的庫(如libstdc++、libgcj等等)。】

在Mac上安裝GCC

如果你安裝了Homebrew的話,只要一行就可以了。

brew install gcc

裝完后用

brew info gcc

或者

gcc -v

看一下是不是成功了


編譯Lua

當你安裝好了編譯器后,編譯lua就變得非常簡單了

Lua官網的文檔里有說編譯方式, 但MakeFile里默認的是編譯成靜態鏈接庫,被這個坑了,后面再說

建議安裝在/opt目錄下

sudo sucd /optcurl -R -O http://www.lua.org/ftp/lua-5.3.4.tar.gztar zxf lua-5.3.4.tar.gzcd lua-5.3.4make macosx testmake macosx install

安裝好后用lua -v查看下如果有信息, 恭喜你,Lua編譯好了!~

下面正式開干了~

寫一個C調用Lua的Demo編譯運行

add.c內容

//你需要include這幾個lua頭文件#include  <stdio.h>#include  "lua.h"#include  "lualib.h"#include  "lauxlib.h"lua_State* L;intluaadd(int x, int y){ int sum; /*函數名*/ lua_getglobal(L,"add"); /*參數入棧*/ lua_pushnumber(L, x); /*參數入棧*/ lua_pushnumber(L, y); /*開始調用函數,有2個參數,1個返回值*/ lua_call(L, 2, 1); /*取出返回值*/ sum = (int)lua_tonumber(L, -1); /*清除返回值的棧*/ lua_pop(L,1); return sum;}intmain(int argc, char *argv[]){ int sum; L = luaL_newstate(); /* 創建lua狀態機 */ luaL_openlibs(L); /* 打開Lua狀態機中所有Lua標準庫 */ /*加載lua腳本*/ luaL_dofile(L, "add.lua"); /*調用C函數,這個里面會調用lua函數*/ sum = luaadd(99, 10); printf("The sum is %d /n",sum); /*清除Lua*/ lua_close(L); return 0;}

add.lua放到與C同級的目錄下,里面寫一個簡單的函數,讓C調用

function add(x,y)  return x + yend 

好了,終于到了用GCC編譯的階段了,直接gcc add.c一下看看行不行。

果然報錯了!

這是因為沒有把add.c里面的函數鏈接到我們前面編譯出來的lua庫里導致的。怎么讓他指定鏈接哪個庫呢?看GCC的文檔得知-l參數可以指定要鏈接的庫

-l參數和-L參數

-l參數就是用來指定程序要鏈接的庫,-l參數緊接著就是庫名,那么庫名跟真正的庫文件名有什么關系呢?

就拿數學庫來說,他的庫名是m,他的庫文件名是libm.so,很容易看出,把庫文件名的頭lib和尾.so去掉就是庫名了

那我們再試一下,gcc add.c -llua,這次編譯出來了: a.out

執行成功!

如何讓Lua調用C?

Lua調用C,我了解到的有3種方式

     1.通過在C中注冊函數給lua調用

     2.封裝成c動態鏈接庫,在lua中require

     3.在LuaJIT里面可以使用ffi高性能的調用C(但是IOS上不支持LuaJIT。。)

1.在C中注冊函數給Lua

lua提供了lua_register函數注冊C函數給lua端調用

hello.c

#include  <stdio.h>#include  <string.h>#include  "lua.h"#include  "lualib.h"#include  "lauxlib.h"static int l_SayHello(lua_State *L){ const char *d = luaL_checkstring(L, 1);//獲取參數,字符串類型 int len = strlen(d); char str[100] = "hello "; strcat(str, d); lua_pushstring(L, str); /* 返回給lua的值壓棧 */ return 1;}intmain(int argc, char *argv[]){ lua_State *L = luaL_newstate(); /* 創建lua狀態機 */ luaL_openlibs(L); /* 打開Lua狀態機中所有Lua標準庫 */ lua_register(L, "SayHello", l_SayHello);//注冊C函數到lua const char* testfunc = "print(SayHello('lijia'))";//lua中調用c函數 if(luaL_dostring(L, testfunc)) // 執行Lua命令。  printf("Failed to invoke./n"); /*清除Lua*/ lua_close(L); return 0;}

gcc -o hello hello.c -llua編譯執行


2.調用C動態鏈接庫

創建一個mylib.c的文件,然后我們把它編譯成動態鏈接庫

#include <stdio.h>#include <math.h>#include <stdarg.h>#include <stdlib.h>#include <lua.h>#include <lauxlib.h>#include <lualib.h>/* 所有注冊給Lua的C函數具有 * "typedef int (*lua_CFunction) (lua_State *L);"的原型。 */static int l_sin(lua_State *L){  // 如果給定虛擬棧中索引處的元素可以轉換為數字,則返回轉換后的數字,否則報錯。 double d = luaL_checknumber(L, 1); lua_pushnumber(L, sin(d)); /* push result */ /* 這里可以看出,C可以返回給Lua多個結果,  * 通過多次調用lua_push*(),之后return返回結果的數量。  */ return 1; /* number of results */}/* 需要一個"luaL_Reg"類型的結構體,其中每一個元素對應一個提供給Lua的函數。 * 每一個元素中包含此函數在Lua中的名字,以及該函數在C庫中的函數指針。 * 最后一個元素為“哨兵元素”(兩個"NULL"),用于告訴Lua沒有其他的函數需要注冊。 */static const struct luaL_Reg mylib[] = { {"mysin", l_sin}, {NULL, NULL}};/* 此函數為C庫中的“特殊函數”。 * 通過調用它注冊所有C庫中的函數,并將它們存儲在適當的位置。 * 此函數的命名規則應遵循: * 1、使用"luaopen_"作為前綴。 * 2、前綴之后的名字將作為"require"的參數。 */extern int luaopen_mylib(lua_State* L){ /* void luaL_newlib (lua_State *L, const luaL_Reg l[]);  * 創建一個新的"table",并將"l"中所列出的函數注冊為"table"的域。  */  luaL_newlib(L, mylib); return 1;}

使用gcc -o mylib.so -fPIC -shared mylib.c -llua -ldl編譯成so

然后創建一個lua文件,把我們編譯出來的c庫引入進來

--[[ 這里"require"的參數對應C庫中"luaopen_mylib()"中的"mylib"。  C庫就放在"a.lua"的同級目錄,"require"可以找到。]]local mylib = require "mylib"-- 結果與上面的例子中相同,但是這里是通過調用C庫中的函數實現。print(mylib.mysin(3.14 / 2)) --> 0.99999968293183

執行a.lua文件,后報錯,說Lua存在多個虛擬機!

lua: multiple Lua VMs detected


為什么呢?查了一些資料發現因為lua默認編譯的是靜態鏈接庫,這樣會導致鏈接多個VM沖突。

那么我們自己再編譯個lua解釋器動態鏈接一下。

mylua.c

#include <stdio.h>#include "lua.h"#include "lualib.h"#include "lauxlib.h"int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L);if (luaL_loadfile(L, "a.lua") || lua_pcall(L, 0, 0, 0)) {  printf("%s", lua_tostring(L, -1)); }}

gcc -o mylua mylua.c -llua -ldl -lm -Wall

這樣就能編譯出mylua可執行文件

在命令行./mylua執行,成功打印出0.99999968293183

總結

gcc命令,編譯lua,編譯C動態鏈接庫這些之前都接觸的比較少。所以也爬了不少坑,哈哈哈。接下來要好好研究下怎么在c中解析二進制協議給lua調用,在c中怎么封裝好luatable

參考資料:

  • https://www.cnblogs.com/pied/archive/2012/10/26/2741601.html
  • http://blog.csdn.net/vermilliontear/article/details/50947379
  • http://blog.csdn.net/casularm/article/details/316149

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美贵妇videos办公室| 久久久精品国产一区二区| 日韩综合中文字幕| 欧美性猛交xxxxx免费看| 欧美尺度大的性做爰视频| 欧美激情成人在线视频| 国产精品高清在线| 色av中文字幕一区| 欧美日本高清一区| 日韩中文视频免费在线观看| 亚洲第一中文字幕| 欧美在线视频免费| 日本亚洲欧洲色α| 欧美精品日韩www.p站| 日韩在线观看免费全集电视剧网站| 国产精品十八以下禁看| 国产成人精品一区二区三区| 日韩专区在线播放| 91亚洲精品在线| 国产精品中文字幕久久久| 在线观看欧美成人| 欧美高跟鞋交xxxxxhd| 久久久精品中文字幕| 91chinesevideo永久地址| 亚洲加勒比久久88色综合| 成人免费高清完整版在线观看| 久久99精品久久久久久噜噜| 国产成人精品一区二区| 国产97在线亚洲| 国产精品69精品一区二区三区| 亚洲欧美日韩爽爽影院| 亚洲第一福利网| 亚洲性夜色噜噜噜7777| 国产精品色悠悠| 亚洲天堂网在线观看| 日韩大片免费观看视频播放| 国产精品久久久久久久久久免费| 97香蕉超级碰碰久久免费软件| 欧美成人一区在线| 国产精品白丝jk喷水视频一区| 国产欧美精品在线播放| 国产男人精品视频| 亚洲免费视频在线观看| 欧美超级乱淫片喷水| 精品综合久久久久久97| 国产精品自产拍高潮在线观看| 中文字幕在线亚洲| 欧美伦理91i| 久久久久国产精品免费| 成人免费淫片视频软件| 国内精品久久久久影院 日本资源| 欧美性高跟鞋xxxxhd| 欧美高跟鞋交xxxxxhd| xxx一区二区| 成人444kkkk在线观看| 日韩av片永久免费网站| 欧美性感美女h网站在线观看免费| 久久在线免费观看视频| 亚洲色图国产精品| 国产精品美女午夜av| 日韩av理论片| 在线成人中文字幕| 日韩综合视频在线观看| 亚洲视频电影图片偷拍一区| 国产精品入口免费视| 大胆欧美人体视频| 在线观看免费高清视频97| 亚洲成人久久久| 九九热在线精品视频| 自拍偷拍亚洲欧美| 成人黄色短视频在线观看| 国产精品对白刺激| 国产日产欧美精品| 欧美在线一区二区视频| 日韩av大片免费看| 美乳少妇欧美精品| 中文字幕亚洲欧美日韩高清| 欧美裸体xxxx极品少妇| 久久精品视频亚洲| 一区二区欧美日韩视频| 国产成人精品免高潮在线观看| 欧美亚洲国产视频小说| 国产精品高潮呻吟视频| 色综合久综合久久综合久鬼88| 色综合天天综合网国产成人网| 亚洲一级一级97网| 日韩视频在线观看免费| 国产成人短视频| 久久精品成人动漫| 欧美大人香蕉在线| 日韩精品中文字幕久久臀| 日韩亚洲国产中文字幕| 国产日产久久高清欧美一区| 国产欧美日韩精品丝袜高跟鞋| 欧美激情欧美激情| 91sao在线观看国产| 欧美性一区二区三区| 91精品国产综合久久香蕉的用户体验| 亚洲欧美激情一区| 欧美华人在线视频| 国产成人在线亚洲欧美| 成人精品福利视频| 日韩电影大全免费观看2023年上| 国产suv精品一区二区| 欧美成人在线影院| 日本久久亚洲电影| 中文字幕无线精品亚洲乱码一区| 欧美电影《睫毛膏》| 亚洲美女黄色片| 91产国在线观看动作片喷水| 亚洲国产天堂久久国产91| 欧美日韩在线视频首页| 久久九九精品99国产精品| 欧美午夜性色大片在线观看| 亚洲一区国产精品| 久久久久久久91| 亚洲最大福利视频网| 成人午夜激情免费视频| 日韩电影视频免费| 裸体女人亚洲精品一区| 66m—66摸成人免费视频| 91色视频在线观看| 欧美怡春院一区二区三区| 国产精品网红直播| 亚洲高清不卡av| 欧美丝袜第一区| 亚洲视频在线看| 欧美精品一区二区免费| 精品国产乱码久久久久久天美| 91日本在线视频| 7777精品久久久久久| 欧美成人三级视频网站| 国产精品久久久久久久9999| 国产精品嫩草影院一区二区| 亚洲福利在线观看| 亚洲欧美国产另类| 亚洲电影在线观看| 亚洲欧美日韩国产成人| 亚洲精品一区av在线播放| 另类少妇人与禽zozz0性伦| 欧美老少配视频| 狠狠干狠狠久久| 国产精品自拍网| 欧美中文字幕在线观看| 精品香蕉一区二区三区| 91久久久久久国产精品| 精品在线欧美视频| 亚洲精品在线观看www| 日韩精品视频在线观看网址| 亚洲国产天堂网精品网站| 91成人天堂久久成人| 91色精品视频在线| 欧美日韩国产激情| 亚洲精品美女久久久| 国产精品久久久av久久久| 国内精品久久久久伊人av| 福利视频导航一区| 国产精品一久久香蕉国产线看观看| 国产欧美日韩精品在线观看| 亚洲www在线| 欧美日韩第一视频| 一本色道久久综合狠狠躁篇怎么玩| 国产精品女人网站| 亚洲第五色综合网|