惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
Last Week in AI
Last Week in AI
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
博客园 - 叶小钗
IT之家
IT之家
Google DeepMind News
Google DeepMind News
D
Docker
J
Java Code Geeks
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
月光博客
月光博客
宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

远飞闲记

用 OpenClaw 搭建全自动晨间简报系统 Open Claw(🦞龙虾): 新手最常踩的 8 个坑,我帮你踩过了 什么是AI Agent(智能体)? OpenClaw 在微信端使用指南 如何让OpenClaw🦞更好用-调教篇 OpenClaw(龙虾🦞)自主赚钱实验笔记 本地Qwen+云模型:OpenClaw真实体验 AI博客主题开发记 OpenClaw初试记 十年博客路:在AI水文泛滥的时代,为何还在坚守? AI Coding实战吐槽:别被"400刀大神"带偏,这些坑我帮你踩过了! 《相信》把不可能变为可能 我们写的程序被杀毒软件杀了,杀毒软件到底杀了什么? 👋2024 探索Unity单元测试:构建可靠游戏代码的基石 实用小黄鸭调试法 炸裂的Unity割韭菜这事 还是要有信念 您好2023 Docker启动提示虚拟化失败 Golang中配置文件热重载方案 重置博客主题 双链知识管理及logseq使用体验 魔幻的魔都疫情 漫谈国内NFT市场状况 如何在UE4中平衡蓝图与C++的使用 2021时光荏苒,2022可遇可期 UE4(Unreal Engine)本地化资源功能 摈弃:“拥有更多=做的更好的”的观念 鱿鱼游戏
Lua和C/C++的数据交互
2015-08-23 · via 远飞闲记

近日重新复习了下C\C++和Lua之间的数据交互知识,在这里也做一个简单的记录来作为以后的参考.

Lua栈操作的介绍

Lua是一种嵌入式的脚本语言,不是独立运行的程序它可以通过链接对其他语言进行扩展,或让其他的语言来使用Lua的功能.其中包括使用lua作为库存在于C中或Lua作为主导权C作为一个库来使用.

lua和C语言的交互都是在一个虚拟栈进行的,所有的API操作都是对栈上的数据进行交互.无论是C到Lua的操作还是Lua到C的操作.这里会存在两个问题

  1. 动态类型和静态类型之间的区别,lua是动态性的语言,而C是静态语言
  2. 自动内存管理和手动内存管理的区别.

lua没有采用C语言的联合来解决动态和静态的区别,其原因是不仅为C一门语言设计的保持Lua的宿主可以是任何一门语言。其次Lua是有垃圾回收机制的如果lua table保持在C变量中,Lua引擎则无法搜索出来回收.所以Lua会使用一个抽象的棧来对Lua和C之间的数据交互.

Lua的栈严格按照(LIFO)先出后进的规范来操作栈,栈中任何元素都保存着lua中的任何类型:

  1. 获得lua中的一个值,调用Lua API函数,Lua会将指定的值压入栈,
  2. 要将一个值传给Lua时则先要将这个值压入栈,调用Lua API函数,Lua则会把获取该值并将其从栈中弹出.

压栈操作会把第一个压入的元素索引标记为1,第二个为2,依次推至栈顶,使用负数来访问栈中元素,-1表示栈顶的元素.

相关API

压入栈:lua_push* (..)
检查元素类型: lua_is*(..)
栈中取出值: lua_to*()
检查栈是否有足够的空间:lua_checkstack(lua_State *l,int size);
返回栈中元素个数:lua_gettop(..)
将栈顶设置为一个指定位置: lua_settop(..)
栈中弹出指定个数的元素:lua_pop(..)
将索引上的值副本压入栈:lua_pushvalue(..)
删除栈中指定位置的元素:lua_remove(..)
移动指定元素空间开辟一个槽空间,将栈顶元素移到该位置: lua_insert(..)
移动栈顶的元素到指定位置:lua_replace(..)
*: string\nil\number\boolean\integer 

C中调用Lua

比如lua文件中有一个全局变量的table: conf={w=20,h=10}


lua_stack* L = luaL_new_state();
luaL_openlibs(L);

lua_dofile("lua文件");

lua_getglobal(lua_stack*,"conf");
if(!lua_istable(lua_stack*,-1))
{
  printf("conf全局变量不是一个table")
}
//获取W的值
lua_pushstring(L,"w");
lua_gettable(L,-2)
if(!lua_isnumber(L,-1))
{
 printf("%s不是一个数字","w");
 }
 int w_val = lua_tonumber(L,-1);
 lua_pop(L,1);

//调用lua中方法
lua_getglobal(L,"方法名");
//这里可以压入参数值
lua_pushstring(L,"参数值")
//状态引用,参数个数,是否有返回值
if(lua_pcall(L,1,1,0)!=0)
{
  printf("函数调用失败 Error:%s",lua_tostring(L,-1));
}
//获取返回值
if(lua_isnumber(L,-1))
{
  int res_value = lua_tonumber(L,-1);
}
lua_close(L);

Lua调用C/C++

注册C/C++函数到Lua中

int mysin(lua_State* L)
{
//获取lua中的值
  int str = luaL_checknumber(L,1);
  printf("lua中传入参数的值:%d",str);
//获取第二个参数,调用lua方法
if(lua_isfunction(L,2))
{
   if(lua_pcall(L,0,0,0)!=0){
      printf("调用函数出错");
    }
}

//压入返回值到lua中
lua_pushstring(L,"这里是返回给lua的值");

return 1;
}

....

//压入函数到栈中
lua_pushcfunction(L,mysin);
lua_setglabal(L,"mysin");
....

lua中直接调用: local res=mysin(10,function()
   print("这里是参数函数")
end);


Lua调用C/C++中的自定义类型

//自定类型绑定到lua中
struct MyType{
  int size;
}

static int mytype_new(lua_State* L)
{
MyType** mytype = (MyType**)lua_newuserdata(L,sizeof(MyType*));
*mytype=new MyType();
luaL_getmetatable(L,"feiio.MyType");
lua_setmetatable(L,-2);
   return 1;
}


static int mytype_getType(lua_State*L)
{
//这里获取创建的对象
MyType **mytype=(MyType**)luaL_checkudata(L,1,"feiio.MyType");
int size = (*mytype)->size;
lua_pushnumber(L,size);
 
 return 1;
 }

//Lua执行对象回收机制销毁对象时调用
static int mytype_gc(lua_State* L)
{
MyType** mytype = (MyType**)luaL_checkudata(L,1,"feiio.MyType");
if(mytype)
{
  delete mytype;
  }
  return 0;
}

int initMyType(lua_State* L)
{
static const luaL_Reg mylib[]={
{"new",mytype_new},
{NULL,NULL}
};

static const luaL_Reg myfunc[]={
{"getType",mytype_getType},
{"__gc",mytype_gc},
{NULL,NULL}
}
//实现面向对象的支持
luaL_newmetatable(L,"feiio.MyType");
lua_pushvalue(L,-1);
lua_setfield(L,-2,"__index");
lua_setfuncs(L,myfunc,0);
  luaL_newlib(L,mylib);


return 1;
  }

//main函数中
.....
initMyType(L);
luaL_requiref(L,"MyType",createType,1);
lua_settop(L,0)
.....

//Lua中调用
local mytype=MyType.new()
//面向对象的方式获取
mytype:getType()

相关资料

使用C++模板来绑定Lua Lua教程:绑定一个简单的C++类(6)