【转】lua和c互相调用的程序示例

虽然也是用programming in lua这本书的给的代码基础上整合的。推荐这本书,挺不错。该程序是lua 和C++之间调用的关系,怎么互相调用函数,怎么创建用户自定义用户。也就是programming in lua 后面第四篇的内容这个程序我是能够运行的。不过注意项目的配置和相应的lua文件路劲要正确。呵呵。加油。*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include<math.h>
#include <assert.h>
#ifdef __cplusplus
extern "C"{
#endif
#include<lua.h>
#include <lauxlib.h>
#include<lualib.h>
#pragma comment(lib, "lua51.lib")
#ifdef __cplusplus
}
#endif


int StackDump(lua_State* L)
{
int nTop = lua_gettop(L); //得到栈的元素个数。栈顶的位置。
printf("The Length of stack is %d\n", nTop); //输出栈顶位置
for (int i = 1; i <= nTop; ++i)
{
   int t = lua_type(L, i);
   printf("%s:", lua_typename(L, t)); //这里的typename是把类型的枚举变成字符串,是类型名。不是栈中的位置。
   switch(t)
   {
   case LUA_TNUMBER:
    printf("%f", lua_tonumber(L, i));
    break;
   case LUA_TSTRING:
    printf("%s", lua_tostring(L, i));
    break;
   case LUA_TTABLE:
    //printf("%s\n", lua_tostring(L,i));
    break;
   case LUA_TFUNCTION:
    //printf("%s\n", lua_tostring(L,i));
    break;
   case LUA_TNIL:
    printf("Is NULL");
    break;
   case LUA_TBOOLEAN:
    printf("%s", lua_toboolean(L, i) ? "true" : "false");
    break;
   default:
    break;
   }
   printf("\n");
}
return 0;
}

int callLuaTest(lua_State* L)
{
if (luaL_loadfile(L, "..\\lua\\1.lua") || lua_pcall(L, 0, 0, 0))
{
   printf("载入lua失败,请检查文件是否正确\n");
}
lua_getglobal(L,"a");
lua_pushstring(L,"c");
lua_gettable(L,-2);
lua_pushvalue(L,-2);
StackDump(L);
if (lua_pcall(L,1,4,0)) //调用函数,调用之后把参数和函数都弹出栈。lua里面table:function() 等价于 table.function(self(table)),所以要多压一个表。
{
   printf("调用函数失败\n");
   return 1;
}
StackDump(L);

return 0;
}

static int L_sin(lua_State* L)
{
double dNumber = luaL_checknumber(L, 1);
lua_pushnumber(L,sin(dNumber));
printf("L_sin\n");
return 1;
}
static int Add(lua_State* L)
{
StackDump(L);
int num1 = (int)lua_tonumber(L,1);
int num2 = (int)lua_tonumber(L,2);
lua_pushnumber(L, num1 + num2);
printf("C Add is called! %d\n", num1 + num2);
StackDump(L);
return 1;
}
static int Sub(lua_State* L)
{
double num1 = luaL_checknumber(L,1);
double num2 = luaL_checknumber(L,2);
lua_pushnumber(L, num1 - num2);
return 1;
}
static int Mul(lua_State* L)
{
double num1 = luaL_checknumber(L,1);
double num2 = luaL_checknumber(L,2);
lua_pushnumber(L, num1 * num2);

return 1;
}
static int Div(lua_State* L)
{
double num1 = luaL_checknumber(L,1);
double num2 = luaL_checknumber(L,2);
lua_pushnumber(L, num1 / num2);
return 1;
}
luaL_Reg myLib[] = {
{"Add", Add},
{"Sub", Sub},
{"Mul", Mul},
{"Div", Div}
}; 
int DumpTest(lua_State* L)
{
lua_settop(L,0);
printf("Test the stack dump\n");

//lua_pushnumber(L, 5); //压入一个数到栈顶
//lua_pushnil(L); //压入一个空到栈顶
//lua_pushstring(L, "This is string Test");//压入一个字符串到栈顶
//lua_pushboolean(L, 1); //要入一个boolean值到栈顶。

//StackDump(L); //打印栈的元素。

//lua_pushvalue(L,-2);
//lua_insert(L,-4);
//StackDump(L); //打印栈的元素。

//lua_replace(L,-4);
//StackDump(L); //打印栈的元素。

//lua_remove(L, -1);
//StackDump(L);

return 0;
}

int callLua(lua_State* L, const char* args, ...)
{
StackDump(L); //查看调用函数的表。
va_list vl; //参数列表的变量
va_start(vl, args); //从args开始来匹配参数
//assert(L && args); //判断参数是否正确
int nTab = 0; //是不是调用table里面的函数,
int nSelf = 0; //是不是self调用,有this
while(*args && *args != '<') //处理要调用的函数
{
   if(*args == 't') //如果是调用表里面的函数
   {
    if (nTab)
    {
     lua_pushstring(L, va_arg(vl, char*)); //把表名压入栈中。
     lua_gettable(L, -2); //得到该表名的表到栈顶
     lua_remove(L, -2); //移除前一个表。
    
    }
    else
    {
     lua_getglobal(L, va_arg(vl, char*));
     //assert(lua_istable(L, -1)); //判断是否是一个表。
     nTab = 1;
    }
   }
   else if (*args == 'f') //普通的函数调用
   {
    if (nTab)
    {
     lua_pushstring(L, va_arg(vl, char*)); //把表名压入栈中。
     lua_gettable(L, -2); //得到该表明的表
     lua_remove(L, -2); //移除前一个表。
    }
    else
    {
     lua_getglobal(L, va_arg(vl, char*));//把表名压入栈中。
    }
   }
   else if (*args == 'F') //如果该函数是一个表里面的函数
   {
    assert(nTab);
    lua_pushstring(L, va_arg(vl, char*)); //把表名压入栈中。
    lua_gettable(L, -2); //得到该表明的表
    lua_pushvalue(L,-2); //把表作为一个参数。
    lua_remove(L, -3); //移除前一个表。
    nSelf = 1;
   }
   ++args;
}
StackDump(L); //查看调用函数的表。
++args; //去掉'<'字符进入参数区域
int nArg = 0; //参数的个数
while (*args && *args != '>') //处理传入的参数
{
   switch(*args)
   {
   case 'i': //int
    lua_pushnumber(L, va_arg(vl, int)); //压入int参数
    break;
   case 'd': //double
    lua_pushnumber(L, va_arg(vl, double)); //压入double参数
    break;
   case 's': //char* string
    lua_pushstring(L, va_arg(vl, char*)); //压入double参数
    break;
   case 'f': //lua调用的C函数
    lua_pushstring(L, va_arg(vl, char*)); //压入double参数
    break;
   default:
    assert(false);
    break;
   }
   ++nArg;
   ++args;
}
StackDump(L); //查看调用函数的表。
++args; //去掉'>'字符,进入返回区域
int nRes = (int)strlen(args);
int i = -nRes; //返回参数的个数。
if (lua_pcall(L,nArg + nSelf, nRes, 0) != 0) //调用lua的函数
{
   printf("调用错误。。。");
   assert(false);
}
StackDump(L); //查看调用函数的表。
nRes = -nRes;
while (*args)
{
   switch(*args)
   {
    case 'i': //int
     *va_arg(vl, int*) = (int)luaL_checknumber(L, nRes); //取得int参数
     break;
    case 'd': //double
     *va_arg(vl, double*) = luaL_checknumber(L, nRes); //取得double参数
     break;
    case 's': //char* string
     strcpy(va_arg(vl, char*), lua_tostring(L, nRes)); //取得字符串
     break;
    case 'f': //lua调用的C函数
     strcpy(va_arg(vl, char*),luaL_checkstring(L, nRes)); //取得字符串
     break;
    default:
     assert(false);
     break;
   }
   ++nRes;
   ++args;
}
StackDump(L); //查看调用函数的表。
lua_settop(L,i -1); //清空栈
StackDump(L); //查看调用函数的表。
va_end(vl);
return 1;
}
int LuaLoadStringTest(lua_State* L)
{

//测试载入字符串并执行。
//char buff[100] = "print(\"good\");"; //要载入的lua语句
luaL_loadbuffer(L, buff, strlen(buff), "line");//将lua语句载入到运行环境中
lua_pcall(L,0,0,0); //在安全模式下执行这些语句。
//std::string str1 = "";
//while (1)
//{
// // fgets(buff, 80, stdin);
// gets(buff);
//if (buff[0] == 0)
//{
// break;
//}

//str1 += buff;
//}
//luaL_loadbuffer(L, str1.c_str(), str1.size(), "line");
//lua_pcall(L,0,0,0);

//DumpTest(L);
return 0;
}
int luaGetVariableTest(lua_State* L)
{
if (luaL_loadfile(L, "..\\lua\\1.lua") || lua_pcall(L, 0, 0, 0))
{
   printf("错误错误\n");
}

lua_settop(L,0);
lua_getglobal(L, "b");
int b = (int)lua_tonumber(L, -1);
StackDump(L);
//printf("%s,", luaL_checkstring(L,-1)); //check也不会自动弹出栈
StackDump(L);
printf("%d\n", b);
return 0;
}
int test1() //指针操作顺序测试。
{
char temp[] = "143456789123";
char* p = temp;
printf("%c",*++p);
return 0;
}

int callLuaTest2(lua_State* L)
{
if (luaL_loadfile(L, "..\\lua\\1.lua") || lua_pcall(L, 0, 0, 0))
{
   printf("文件装载错误。。");
   return -1;
}
char reChars[100];
//callLua(L, "f<>s", "test", reChars);
//printf("%s\n", reChars);
int i1, i2;
double d1;
char c2[100];
callLua(L, "ttf<idsis>idsis", "a", "f", "a", 23, 34.56, "Ceshi", 34, "哈哈",&i1,&d1,reChars, &i2,c2);
callLua(L,"tF<idsis>idsis", "a", "d", 23, 34.56, "Ceshi", 34, "哈哈",&i1,&d1,reChars, &i2,c2);
callLua(L, "f<", "test");
StackDump(L);//注意,调用lua之后栈是不会清空的。
return 0;
}
int test2(lua_State* L)
{
if (luaL_loadfile(L,"..\\lua\\1.lua"))
{
   printf("LoadError\n");
}
StackDump(L);
lua_pushcfunction(L, Add);
lua_setglobal(L, "Add"); //set之后他就会把压入的栈弹出去。
StackDump(L);
if (lua_pcall(L,0,0,0))
{
   printf("文件执行错误\n");
}
StackDump(L);
return 0;
}

int luaCallCTest(lua_State* L)
{
luaL_openlib(L, "_G", myLib, 0);
if (luaL_loadfile(L,"..\\lua\\1.lua") || lua_pcall(L,0,0,0))
{
   printf("载入lua文件失败。\n");
}
return 0;
}

int test3(lua_State* L)
{

lua_pushlightuserdata(L, (void*)Add);
lua_pushstring(L,"Add");
lua_settable(L,LUA_REGISTRYINDEX); //这个是lua做处理的。呵呵。挺强大
StackDump(L);
lua_pushlightuserdata(L,(void*)Add);
lua_gettable(L, LUA_REGISTRYINDEX);
StackDump(L);
return 1;
}

//==============================================================================================
//和自定义类型数组相关
struct NumArray
{
size_t nSize;
double values[1];
};
static int NewArray(lua_State* L)
{
int nSize = luaL_checkinteger(L, 1); 
NumArray* pArray= (NumArray*)lua_newuserdata(L, sizeof(NumArray) + (nSize) * sizeof(double));
pArray->nSize = nSize;
//StackDump(L);
luaL_getmetatable(L, "NumArrayReg");
lua_setmetatable(L,-2);
//StackDump(L); //luaL_getmetatable 和 setmetatable 执行结束后会自动出栈。
return 1;
}
static NumArray* CheckNumArray(lua_State* L, int Ind)
{
NumArray* arr = (NumArray*)luaL_checkudata(L, Ind, "NumArrayReg"); //哈哈,有效果,可以判断类型。我觉得错误提示也忒不仔细了,只是一个载入错误。
luaL_argcheck(L, arr, Ind, "类型转换错误。");
return arr;

}
static int GetArrayValue(lua_State* L)
{
//StackDump(L);
NumArray* pArray = CheckNumArray(L,1);
unsigned int nInd = luaL_checkinteger(L, 2);
luaL_argcheck(L, nInd >= 1 && nInd <= pArray->nSize, 2, "数组越界");
lua_pushnumber(L, pArray->values[nInd]);
//StackDump(L);
return 1;
}

static int SetArrayValue(lua_State* L)
{
//StackDump(L);
NumArray* pArray = CheckNumArray(L,1);
luaL_argcheck(L, pArray != NULL, 1, "读取数组错误");
int nInd = (int)luaL_checkinteger(L, 2);
//luaL_argcheck(L, nInd >= 1 && nInd <= pArray->nSize, 2, "数组越界");
double dValue = luaL_checknumber(L, 3);
pArray->values[nInd] = dValue;
return 1;
}
luaL_Reg NumArrayCls[] = {
{"NewArray",NewArray},
{NULL, NULL}
}; 
luaL_Reg NumArrayFuc[] = { 
{"GetArrayValue",GetArrayValue},
{"SetArrayValue", SetArrayValue},
{NULL,NULL}
};

static int OpenArrayLib(lua_State* L)
{
//StackDump(L);
luaL_newmetatable(L, "NumArrayReg");//这里不会自动出栈。要手动的。
lua_pushstring(L,"__index");
lua_pushvalue(L, -2);
lua_settable(L,-3); //他也会出栈,是索引和值出战,表不会出栈;
//StackDump(L);
luaL_openlib(L, NULL, NumArrayFuc, 0); //如果不是null就是增加弄一个表,是null就是添加到他上一个表。
luaL_openlib(L, "NumArray", NumArrayCls, 0); //添加类的函数。。这里也不会出栈
//StackDump(L);
lua_settop(L,-3); //弹出栈。

return 1;
}
int userdataTest(lua_State* L)
{

OpenArrayLib(L);
//StackDump(L);
//lua_newuserdata(L, sizeof(int));
//lua_setglobal(L, "Test");
//StackDump(L); //这里会自动出栈。。
if (luaL_loadfile(L,"..\\lua\\1.lua") || lua_pcall(L,0,0,0))
{
   printf("载入lua文件失败。\n");
}

return 0;
}
//================================================================================================================

static int test4(lua_State* L)
{

return 1;
}
int main()
{
lua_State* L = lua_open(); //创建一个LUA运行环境。
luaopen_base(L); //打开一些lua基本的库.
luaopen_table(L);
luaopen_string(L);
luaopen_math(L);
lua_settop(L,0);
//luaCallCTest(L);
userdataTest(L);
//test3(L);
lua_close(L);
getchar();
return 0;
}

//callLuaTest(L);
//StackDump(L); //注意,调用lua之后栈是不会清空的。
//callLuaTest2(L); //调用Lua的通用方法
//test2(L); //测试压入一个C函数。
/*
这里主要要在项目配置里面->属性->c/c++->附加包含目录把头文件包含进来。我的是..\..\common\lua\include
属性->连接器->附加库目录把库文件包含进来。我的是..\..\common\lua\lib
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的示例程序,其中Lua调用了C函数,C函数又回调了Lua函数。 C代码: ```c #include <stdio.h> #include "lua.h" #include "lualib.h" #include "lauxlib.h" static int c_hello(lua_State *L) { printf("Hello from C!\n"); return 0; } static int c_call_lua(lua_State *L) { const char *str = luaL_checkstring(L, 1); printf("C calling Lua: %s\n", str); lua_pushinteger(L, 12345); lua_pushstring(L, "Hello from Lua!"); return 2; } static int c_call_lua_callback(lua_State *L) { const char *str = luaL_checkstring(L, 1); lua_Integer num = luaL_checkinteger(L, 2); luaL_checktype(L, 3, LUA_TFUNCTION); lua_pushvalue(L, 3); // 把回调函数压入栈中 lua_pushstring(L, str); lua_pushinteger(L, num); int result = lua_pcall(L, 2, 1, 0); // 调用回调函数 if (result != 0) { printf("Error calling Lua callback: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); return 0; } const char *ret_str = lua_tostring(L, -1); printf("C received from Lua callback: %s\n", ret_str); return 0; } int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_pushcfunction(L, c_hello); lua_setglobal(L, "c_hello"); lua_pushcfunction(L, c_call_lua); lua_setglobal(L, "c_call_lua"); lua_pushcfunction(L, c_call_lua_callback); lua_setglobal(L, "c_call_lua_callback"); luaL_dostring(L, "function lua_hello() print('Hello from Lua!') end"); luaL_dostring(L, "c_hello()"); luaL_dostring(L, "print(c_call_lua('Hello from C!'))"); luaL_dostring(L, "c_call_lua_callback('Hello from C callback!', 123, function(str, num) print('Lua callback received:', str, num) return 'Hello from Lua callback!' end)"); lua_close(L); return 0; } ``` Lua代码: ```lua local function lua_callback(str, num) print("Lua received from C callback:", str, num) return "Hello from Lua callback!" end c_hello() local num, str = c_call_lua("Hello from Lua!") print("Lua received from C:", num, str) c_call_lua_callback("Hello from Lua callback!", 123, lua_callback) ``` 在运行该程序时,会输出以下内容: ``` Hello from C! 12345 Hello from Lua! Lua callback received: Hello from C callback! 123 C received from Lua callback: Hello from Lua callback! Lua received from C callback: Hello from Lua callback! 123 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值