当前位置: 首页 > news >正文

大话C与Lua(五) 面向对象的数据结构——userdata

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

 

如何实现面向对象?

 

    熟悉Lua的同学都知道!在Lua内部已经实现了面向对象的基本机制(table);

    同时也为宿主语言(在这里是C语言)提供了一套自定义数据结构(userdata)。所以,我们可以简单的利用metatable与__index的访问机制,为userdata实现一套简单的面向对象的访问方式。

 

stu.c

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>


typedef struct _Student
{
	const char * strName ; // 学生姓名
	int strNum ; // 学号
	int iSex ; // 学生性别
	int iAge ; // 学生年龄
}Student;

int lnew(lua_State* L){
	Student *stu =  lua_newuserdata(L,sizeof(Student));
	if(NULL == stu){
		return 0;
	}
	luaL_setmetatable(L,"stu");
	return 1;
}

int lset(lua_State* L){
	Student *stu = luaL_checkudata(L,1,"stu");
	stu->strName = luaL_checkstring(L,2);
	stu->strNum = luaL_checkinteger(L,3);
	stu->iSex = luaL_checkinteger(L,4);
	stu->iAge = luaL_checkinteger(L,5);
	return 0;
}

int lget(lua_State* L){
	Student *stu = luaL_checkudata(L,1,"stu");
	lua_pushstring(L,stu->strName);
	lua_pushinteger(L,stu->strNum);
	lua_pushinteger(L,stu->iSex);
	lua_pushinteger(L,stu->iAge);
	return 4;
}

const luaL_Reg mylib[] = {
	{"new",lnew},
	{"set",lset},
	{"get",lget},
	{NULL,NULL}
};


LUA_API int luaopen_stu(lua_State* L){
	luaL_newmetatable(L,"stu");
	lua_pushstring (L,"__index");
	lua_pushvalue(L,-2);
	lua_rawset(L,-3);
	luaL_setfuncs(L,mylib,0);


	luaL_newlib(L,mylib);
	return 1;
}

main.lua

local stu = require "stu"

local stu = stu.new()
print(stu)
stu:set("Candy",1024,1,26)
local name,id,sex,age = stu:get()
print(name,id,sex,age)

 

运行结果:

[root@localhost ~]# cc -o stu.so stu.c  -Wall -O2 -fPIC -shared -std=gnu99
[root@localhost ~]# lua main.lua 
stu: 0x19380d8
Candy	1024	1	26
[root@localhost ~]# 

 

运行结果很简单。现在,我们简要分析一下具体实现步奏。

 

首先我们在注册表创建了一个metatable,并且起名"stu"。

然后为这个元表添加一个__index元方法,然后将自身作为键值查找域。

最后使用setfuncs为元表注入方法。

 

上述步奏等效于lua中如下操作:

local meta = {1,2,3}
local t = setmetatable({},{__index=meta})

print(t[1])

 

 

这里需要注意的是:

    full userdata的生命周期是由Lua来管理的。

    如果由Lua gc回收了userdata的使用空间,C语言还引用原地址将会引起段错误。

    所以如果需要完全使用C API来管理 userdata是生命周期,请使用light userdata。

转载于:https://my.oschina.net/CandyMi/blog/1305292

相关文章:

  • JAX-WS客户端中引用jar包中的WSDL文件的方法
  • 微软修复了Office套件中“保护视图”功能可被绕过的一个安全漏洞
  • 静电导致笔记本不能开机?
  • .pyc 想到的一些问题
  • 《互联网时代的软件革命--SaaS架构设计》即将第3次印刷
  • Whitelabel Error Page 专题
  • 大数据应用实施意见出台 实现数据共享与开放
  • 纸的折法(包括:枫叶,梅花,千纸鹤,小狗,豹子,蛇,大象,狐狸,鹅,老鼠,猴子,骆驼,蜻蜓,蝎子,瓢虫,螳螂,蜜蜂,船和小猫咪)...
  • MySQL---常见函数
  • 一起来看流星雨剧情简介/剧情介绍/剧情分集介绍第二集
  • 厦门出海SaaS项目笨鸟社交获数千万元A轮投资 东方富海领投
  • Nehalem EX将改变HPC市场的格局
  • 问题-DelphiXE10.2怎么安装文本转语音(TTS)语音转文本(SR)控件(XE10.2+WIN764)
  • 角色分配与操作权限分配设计思路
  • [第五组E]用例:活动浏览+功能说明书+技术说明书
  • hexo+github搭建个人博客
  • 2017-08-04 前端日报
  • Android开源项目规范总结
  • CentOS 7 修改主机名
  • CentOS从零开始部署Nodejs项目
  • Electron入门介绍
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Netty 4.1 源代码学习:线程模型
  • Python - 闭包Closure
  • react 代码优化(一) ——事件处理
  • Ruby 2.x 源代码分析:扩展 概述
  • 从0实现一个tiny react(三)生命周期
  • 仿天猫超市收藏抛物线动画工具库
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 目录与文件属性:编写ls
  • 前端js -- this指向总结。
  • 嵌入式文件系统
  • 如何设计一个比特币钱包服务
  • 微信开放平台全网发布【失败】的几点排查方法
  • 在Mac OS X上安装 Ruby运行环境
  • #define用法
  • #ubuntu# #git# repository git config --global --add safe.directory
  • (1)Android开发优化---------UI优化
  • (1)bark-ml
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (转)JAVA中的堆栈
  • (转)Oracle存储过程编写经验和优化措施
  • (转)Sql Server 保留几位小数的两种做法
  • (转)Unity3DUnity3D在android下调试
  • (转载)Linux 多线程条件变量同步
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET Reactor简单使用教程
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • /dev下添加设备节点的方法步骤(通过device_create)
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理