最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言與Lua之間的相互調(diào)用詳解

 更新時間:2018年01月15日 09:39:22   作者:那個少年  
這篇文章主要給大家介紹了關(guān)于C語言與Lua之間的相互調(diào)用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。

前言

第一次接觸Lua是因?yàn)閁nity游戲中需要熱更,但是一直沒搞懂Lua是怎么嵌入到別的語言中執(zhí)行的,如何互相調(diào)用的。

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

那么如何使用Lua語言?

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

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

在Mac上安裝GCC

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

brew install gcc

裝完后用

brew info gcc

或者

gcc -v

看一下是不是成功了


編譯Lua

當(dāng)你安裝好了編譯器后,編譯lua就變得非常簡單了

Lua官網(wǎng)的文檔里有說編譯方式, 但MakeFile里默認(rèn)的是編譯成靜態(tài)鏈接庫,被這個坑了,后面再說

建議安裝在/opt目錄下

sudo su
cd /opt
curl -R -O http://www.lua.org/ftp/lua-5.3.4.tar.gz
tar zxf lua-5.3.4.tar.gz
cd lua-5.3.4
make macosx test
make macosx install

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

下面正式開干了~

寫一個C調(diào)用Lua的Demo編譯運(yùn)行

add.c內(nèi)容

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

add.lua放到與C同級的目錄下,里面寫一個簡單的函數(shù),讓C調(diào)用

function add(x,y)
  return x + y
end 

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

果然報錯了!

這是因?yàn)闆]有把a(bǔ)dd.c里面的函數(shù)鏈接到我們前面編譯出來的lua庫里導(dǎo)致的。怎么讓他指定鏈接哪個庫呢?看GCC的文檔得知-l參數(shù)可以指定要鏈接的庫

-l參數(shù)和-L參數(shù)

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

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

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

執(zhí)行成功!

如何讓Lua調(diào)用C?

Lua調(diào)用C,我了解到的有3種方式

     1.通過在C中注冊函數(shù)給lua調(diào)用

     2.封裝成c動態(tài)鏈接庫,在lua中require

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

1.在C中注冊函數(shù)給Lua

lua提供了lua_register函數(shù)注冊C函數(shù)給lua端調(diào)用

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);//獲取參數(shù),字符串類型
 int len = strlen(d);
 char str[100] = "hello ";
 strcat(str, d);
 lua_pushstring(L, str); /* 返回給lua的值壓棧 */
 return 1;
}
int
main(int argc, char *argv[])
{
 lua_State *L = luaL_newstate(); /* 創(chuàng)建lua狀態(tài)機(jī) */
 luaL_openlibs(L); /* 打開Lua狀態(tài)機(jī)中所有Lua標(biāo)準(zhǔn)庫 */
 lua_register(L, "SayHello", l_SayHello);//注冊C函數(shù)到lua
 const char* testfunc = "print(SayHello('lijia'))";//lua中調(diào)用c函數(shù)
 if(luaL_dostring(L, testfunc)) // 執(zhí)行Lua命令。
  printf("Failed to invoke.\n");

 /*清除Lua*/
 lua_close(L);
 return 0;
}

gcc -o hello hello.c -llua編譯執(zhí)行


2.調(diào)用C動態(tài)鏈接庫

創(chuàng)建一個mylib.c的文件,然后我們把它編譯成動態(tài)鏈接庫

#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
/* 所有注冊給Lua的C函數(shù)具有
 * "typedef int (*lua_CFunction) (lua_State *L);"的原型。
 */
static int l_sin(lua_State *L)
{ 
 // 如果給定虛擬棧中索引處的元素可以轉(zhuǎn)換為數(shù)字,則返回轉(zhuǎn)換后的數(shù)字,否則報錯。
 double d = luaL_checknumber(L, 1);
 lua_pushnumber(L, sin(d)); /* push result */

 /* 這里可以看出,C可以返回給Lua多個結(jié)果,
  * 通過多次調(diào)用lua_push*(),之后return返回結(jié)果的數(shù)量。
  */
 return 1; /* number of results */
}
/* 需要一個"luaL_Reg"類型的結(jié)構(gòu)體,其中每一個元素對應(yīng)一個提供給Lua的函數(shù)。
 * 每一個元素中包含此函數(shù)在Lua中的名字,以及該函數(shù)在C庫中的函數(shù)指針。
 * 最后一個元素為“哨兵元素”(兩個"NULL"),用于告訴Lua沒有其他的函數(shù)需要注冊。
 */
static const struct luaL_Reg mylib[] = {
 {"mysin", l_sin},
 {NULL, NULL}
};
/* 此函數(shù)為C庫中的“特殊函數(shù)”。
 * 通過調(diào)用它注冊所有C庫中的函數(shù),并將它們存儲在適當(dāng)?shù)奈恢谩?
 * 此函數(shù)的命名規(guī)則應(yīng)遵循:
 * 1、使用"luaopen_"作為前綴。
 * 2、前綴之后的名字將作為"require"的參數(shù)。
 */
extern int luaopen_mylib(lua_State* L)
{
 /* void luaL_newlib (lua_State *L, const luaL_Reg l[]);
  * 創(chuàng)建一個新的"table",并將"l"中所列出的函數(shù)注冊為"table"的域。
  */ 
 luaL_newlib(L, mylib);

 return 1;
}

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

然后創(chuàng)建一個lua文件,把我們編譯出來的c庫引入進(jìn)來

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

執(zhí)行a.lua文件,后報錯,說Lua存在多個虛擬機(jī)!

lua: multiple Lua VMs detected


為什么呢?查了一些資料發(fā)現(xiàn)因?yàn)閘ua默認(rèn)編譯的是靜態(tài)鏈接庫,這樣會導(dǎo)致鏈接多個VM沖突。

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

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可執(zhí)行文件

在命令行./mylua執(zhí)行,成功打印出0.99999968293183

總結(jié)

gcc命令,編譯lua,編譯C動態(tài)鏈接庫這些之前都接觸的比較少。所以也爬了不少坑,哈哈哈。接下來要好好研究下怎么在c中解析二進(jìn)制協(xié)議給lua調(diào)用,在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

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • C++11?成員函數(shù)作為回調(diào)函數(shù)的使用方式

    C++11?成員函數(shù)作為回調(diào)函數(shù)的使用方式

    這篇文章主要介紹了C++11?成員函數(shù)作為回調(diào)函數(shù)的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++錯誤使用迭代器超出引用范圍問題及解決方案

    C++錯誤使用迭代器超出引用范圍問題及解決方案

    這篇文章主要介紹了C++錯誤使用迭代器超出引用范圍分析與解決,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • QT實(shí)現(xiàn)二、八、十六進(jìn)制之間的轉(zhuǎn)換

    QT實(shí)現(xiàn)二、八、十六進(jìn)制之間的轉(zhuǎn)換

    本文主要介紹了QT實(shí)現(xiàn)二、八、十六進(jìn)制之間的轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C語言中數(shù)組排序淺析

    C語言中數(shù)組排序淺析

    這篇文章主要為大家介紹了C語言算法練習(xí)中數(shù)組元素排序的四種類型,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2022-12-12
  • C++編寫DLL動態(tài)鏈接庫的步驟與實(shí)現(xiàn)方法

    C++編寫DLL動態(tài)鏈接庫的步驟與實(shí)現(xiàn)方法

    這篇文章主要介紹了C++編寫DLL動態(tài)鏈接庫的步驟與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了C++導(dǎo)出類文件及生成與調(diào)用DLL動態(tài)連接庫的相關(guān)操作技巧,需要的朋友可以參考下
    2016-08-08
  • C++11新特性之智能指針(shared_ptr/unique_ptr/weak_ptr)

    C++11新特性之智能指針(shared_ptr/unique_ptr/weak_ptr)

    這篇文章主要介紹了C++11新特性之智能指針,包括shared_ptr, unique_ptr和weak_ptr的基本使用,感興趣的小伙伴們可以參考一下
    2016-08-08
  • C++ 風(fēng)靡一時的連連看游戲的實(shí)現(xiàn)流程詳解

    C++ 風(fēng)靡一時的連連看游戲的實(shí)現(xiàn)流程詳解

    游戲“連連看”是源自臺灣的桌面小游戲,自從流入大陸以來風(fēng)靡一時,也吸引眾多程序員開發(fā)出多種版本的“連連看”。這其中,顧芳編寫的“阿達(dá)連連看”以其精良的制作廣受好評,這也成為顧方“阿達(dá)系列軟件”的核心產(chǎn)品。并于2004年,取得國家版權(quán)局的計(jì)算機(jī)軟件登記證書
    2021-11-11
  • C/C++?for?語句的要點(diǎn)與注意事項(xiàng)小結(jié)

    C/C++?for?語句的要點(diǎn)與注意事項(xiàng)小結(jié)

    C/C++ 中的?for?語句是一種常用的循環(huán)結(jié)構(gòu),用于重復(fù)執(zhí)行一段代碼,直到滿足某個條件為止,這篇文章主要介紹了C/C++?for?語句的要點(diǎn)與注意事項(xiàng),需要的朋友可以參考下
    2024-06-06
  • C語言main()函數(shù)的參數(shù)問題詳解

    C語言main()函數(shù)的參數(shù)問題詳解

    這篇文章主要為大家詳細(xì)介紹了C語言main()函數(shù)的參數(shù)問題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • c++統(tǒng)計(jì)文件中字符個數(shù)代碼匯總

    c++統(tǒng)計(jì)文件中字符個數(shù)代碼匯總

    本文給大家匯總介紹了3種使用C++實(shí)現(xiàn)統(tǒng)計(jì)文件中的字符個數(shù)的方法,非常的簡單實(shí)用,有需要的小伙伴可以參考下。
    2015-09-09

最新評論

台江县| 中山市| 乌兰察布市| 庆阳市| 兴和县| 栾川县| 洪雅县| 仲巴县| 时尚| 巩义市| 麻江县| 确山县| 缙云县| 鄄城县| 忻州市| 容城县| 雅江县| 崇阳县| 茌平县| 临城县| 灌南县| 合川市| 迁安市| 会同县| 黑河市| 金阳县| 天台县| 合作市| 通城县| 水城县| 自治县| 南雄市| 桃源县| 宝坻区| 赤水市| 安义县| 华亭县| 连城县| 灌阳县| 金门县| 绥德县|