国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

lua編程之lua與C相互調(diào)用

2019-11-14 17:32:31
字體:
供稿:網(wǎng)友

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)用的方法。

Lua與C相互調(diào)用的首要問題是如何交換數(shù)據(jù),lua API使用了一個抽象的棧與C語言交換數(shù)據(jù),提供了壓入元素,查詢元素和彈出元素等功能的API操作棧,這里可以查看lua5.2中每個函數(shù)的詳細(xì)文檔,棧中的元素可以通過索引訪問,從棧底向上是從1開始遞增的正整數(shù),從棧頂向下是從-1開始遞減的負(fù)整數(shù),棧的元素按照FIFO的規(guī)則進(jìn)出。

一、 C調(diào)用lua

先通過一個簡單的例子了解C是怎么調(diào)用lua的,

//test.luawidth = 10height = 20//test.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, "test.lua") || lua_pcall(L, 0,0,0)){    PRintf("error %s/n", lua_tostring(L,-1));    return -1;  }  lua_getglobal(L,"width");  lua_getglobal(L,"length");  printf("width = %d/n", lua_tointeger(L,-2));  printf("length = %d/n", lua_tointeger(L,-1));  lua_close(L);  return 0;}

luaL_newstate創(chuàng)建一個新的lua_State,C和lua的所有操作都要依賴這個lua環(huán)境, luaL_openlibs將lualib.h中定義的lua標(biāo)準(zhǔn)庫加載到進(jìn)lua_State。

luaL_loadfile從文件中加載lua代碼并編譯,編譯成功后的程序塊被壓入棧中,

lua_pcall會將程序塊彈出并在保護(hù)模式下解釋執(zhí)行。代碼中調(diào)用lua_pcall就在lua_State中定義了 width和 length兩個全局變量。

lua_getglobal將全局變量的值壓入棧中,width先入棧,在-2的位置,length在棧頂。

除了變量,C代碼還可以直接調(diào)用lua中定義的函數(shù)

//test.luafunction add(x, y)  return x+yend//test.c#include <stdio.h>#include <lua.h>#include <lualib.h>#include <lauxlib.h>#include <math.h>int main() {  lua_State *L = luaL_newstate();  luaL_openlibs(L);  if(luaL_loadfile(L, "test.lua") || lua_pcall(L, 0,0,0)){    printf("error %s/n", lua_tostring(L,-1));    return -1;  }  lua_getglobal(L,"add");  lua_pushnumber(L, 10);  lua_pushnumber(L, 20);  if(lua_pcall(L, 2, 1, 0) != 0){    printf("error %s/n", lua_tostring(L,-1));    return -1;  }  double z = lua_tonumber(L, -1);  printf("z = %f /n", z);  lua_pop(L, 1);  lua_close(L);  return 0;}

lua_pcall(L, 2, 1, 0)表示,傳入兩個參數(shù),期望得到一個返回值,0表示錯誤處理函數(shù)在棧中的索引值,壓入結(jié)果前會彈出函數(shù)和參數(shù),所以z的索引是-1.

二、 lua調(diào)用C

lua可以將C函數(shù)注冊到lua中,C函數(shù)必須遵循統(tǒng)一的原型,這個原型定義在lua.h中,

typedef int (*) (lua_State *)

用C函數(shù)擴(kuò)展lua時,一般將所有的C函數(shù)編譯成一個獨(dú)立的模塊,方便增加新的函數(shù)。

//mylib.c#include <stdio.h>#include <lua.h>#include <lualib.h>#include <lauxlib.h>#include <math.h>static int myadd(lua_State *L){                int a = luaL_checknumber(L, 1);                int b = luaL_checknumber(L, 2);                lua_pushnumber(L, a+b);                return 1;}static const struct luaL_Reg mylib [] = {        {"add", myadd},         {NULL, NULL}};int luaopen_mylib(lua_State *L){  luaL_newlib(L, mylib);  return 1;}//call.lua#!/usr/local/bin/lualib=require "mylib"print(lib.add(1, 2))

每個被lua調(diào)用的C函數(shù)都有自己的私有棧,壓入?yún)?shù)的索引從1開始遞增,結(jié)果值也是直接壓入棧中,函數(shù)返回時會將壓入的參數(shù)全部刪除,只留下結(jié)果值。mylib[]聲明了模塊中所有C函數(shù)列表,每一項(xiàng)映射了C函數(shù)在lua中的命名,比如上面代碼中myadd函數(shù)在lua中用add表示,列表必須用{NULL, NULL}結(jié)束。 luaL_newlib在棧中創(chuàng)建一個table,將mylib數(shù)組中的C函數(shù)注冊進(jìn)這個table中。 luaopen_mylib將這個table中的函數(shù)加載進(jìn)lua環(huán)境中。

先將C代碼編譯成動態(tài)鏈接庫,

gcc -shared -fPIC -o mylib.so mylib.c -llua -lm -ldl

lua代碼中,require會查找 mylib.so,并調(diào)用該鏈接庫中的 luaopen_mylib,luaopen_的后綴必須與動態(tài)鏈接庫名字一樣,這是由require查找函數(shù)方式?jīng)Q定的。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 乌兰察布市| 吴川市| 西乌珠穆沁旗| 红河县| 井陉县| 奉化市| 思南县| 广丰县| 宁海县| 重庆市| 泊头市| 广西| 宜君县| 石城县| 荣昌县| 西贡区| 河津市| 武城县| 建始县| 沅陵县| 习水县| 上饶市| 岳池县| 云南省| 梧州市| 河西区| 道孚县| 乌兰察布市| 巩义市| 泌阳县| 平山县| 静海县| 西宁市| 凤山市| 长兴县| 长寿区| 南和县| 永安市| 富川| 英超| 博爱县|