lua与C#交互原理

lua 与c#交互原理
自从ulua在官网上出来后,lua 就被U3D开发人员喜爱。国内有几个高手把lua拿过来 接着进行了封装。很多都是新手转过来。lua语法一看遍知,但是大多数人还是不明白两个语言之间的互相调用是怎么一回事,这也是难点和重点。所以今天想跟大家分享一下这方面的知识,让大家少走弯路吧。
先看看u3d 里面c# 调用lua 是c# 先调用了lua的dll它是一个C库这个C库又调用了lua的东西这样才实现了c#和lua的一个通信.
所以我们先来分析一下c与lua:
C与lua交互面临以下几个问题:    1, 由于lua里面的数据都是动态加载的所以内存也是动态分配的,也没有static 这样的修饰,而C里面有 static const 这样的静态类型数据    2, c里面是手动管理内存lua 里面是自动管理内存
所以为了解决这些问题就采用了一个抽象栈来让lua与c交换值,好比c里面的 void*  可以指向任何地址而不用管存储类型。这样两边都不管你传的何种类型的参数,只用知道它是一个地址指针。两边用的时候再强制转换成对应的类型。
我们看一下C调用lua示例:
在lua中定义一个table :background = {r=0.30, g=0.10, b=0}在c中这样取这些值
#define MAX_COLOR       255先定义了一个函数 供以下使用:int getfield (const char key) {    int result;lua_pushstring(L, key);      //将参数 key 栈为2或者-1入栈lua_gettable(L, -2);  //  它会将栈顶做为key并将value返回到栈顶    if (!lua_isnumber(L, -1)) //栈顶值判断是否是一个数字       error(L, “invalid component in background color”);result = (int)lua_tonumber(L, -1) * MAX_COLOR;   //将返回的栈顶值拿来进行强制转换 int    lua_pop(L, 1);  / remove number */    return result;}
这是咱们lua程序的起始位置 假设前面的lua环境已经加载好了:
lua_getglobal(L, “background”);  // 这句话将lua 表background获取放在栈 1的位置if (!lua_istable(L, -1))    error(L, “`background’ is not a valid color table”);
red = getfield(“r”);green = getfield(“g”);blue = getfield(“b”);

具体分析:第一步: lua_getglobal(L, “background”);  //这句话将lua 表background获取放在栈1的位置
第二步:  getfield(“r”);     lua_pushstring(L, key);      //将参数“r”key栈为2或者-1入栈

第三步:    lua_gettable(L, -2);   //它会将栈顶做为key并将value返回到栈顶并去除 r (这个地方是lua内部的协议就会默认的将表以上的栈作为参数key传入并返回值将key去除)

第四步:   result = (int)lua_tonumber(L, -1) * MAX_COLOR;   //将返回的栈顶值拿来进行强制转换 int

第五步:  lua_pop(L, 1);  //将栈顶也就是result进行剔除栈

这样 c 就拿到了变量   red
注意:    栈索引既可以是正数索引也可以是负数, 正数最底下的为1最上面的为-1 lua_gettable(L, -2);   //这个地方是lua内部的协议: 1,表以上的栈作为参数key传入 2,将key从栈中去除 3,并返回值放入栈顶
 这是lua跟C传参的内置协议大家要明白了它就会有这么几步操作。
lua 调用C :第一步:定义c函数
向lua注册的函数必须要有这样的结构返回值为int传入参数为lua_State*typedef int (*lua_CFunction) (lua_State *L);
所以:static int l_sin (lua_State *L) {double d = lua_tonumber(L, 1);  /*第一个参数总是在这个私有栈的index=1的位置//获取参数  /lua_pushnumber(L, sin(d));      / 第结果放入栈中 /return 1;                      / number of results */}

第二步向lua注册:
lua_pushcfunction(l, l_sin);  // 这里相信大家要知道为啥u3d里面要注册wrap文件了lua_setglobal(l, “mysin”);
第三步:lua调用:
  reuslt = mysin(45)  // 取出的就是栈顶的值 
分析 :
调用 reuslt = mysin(45)实则是调用: 
static int l_sin (lua_State L) {double d = lua_tonumber(L, 1);  /   获取参数 45  /lua_pushnumber(L, sin(d));      / 第结果放入栈顶就是返回给 reuslt   /return 1;                       / number of results */}

注意: 1,每一个函数都有一个私有栈并且第一个参数就是在栈的1位置,后面以此类推有几个参数就有多少个 2,如果函数返回结果,第一个结果被第一个入栈,因此如果有n个返回结果,第一个返回结果在栈中的位置为-n,最后一个返回结果在栈中的位置为-1
c#就是在这基础之上又调用了C api所以相信大家在看c#与lua也就明白很多了。也知道为什么要进行wrap,wrap之后为什么可以直接使用了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值