根包含文件——Luaconf.h (src)收藏

根包含文件——Luaconf.h (src) Luaconf.h是配置的总集, 定义了平台相关的设置,是所有文件都包含的,即Rootly Included。0. 前言开始关注Lua也是06年六月的事情,《程序员》的2006年第六期中,我独独看中了Lua,而不是当时我已经比较熟悉的Python和Ruby,即使它们我都关注了好几年,但是都没有Lua给我的震撼大。于是那个夏天,稍微地尝试读了Lua的代码。开学后,我突然觉得自己有 阅读详情
   根包含文件——Luaconf.h (src)收藏

新一篇: C1902 | 旧一篇: Lock-free论文集

Luaconf.h是配置的总集, 定义了平台相关的设置,是所有文件都包含的,即Rootly Included。

0. 前言

开始关注Lua也是06年六月的事情,《程序员》的2006年第六期中,我独独看中了Lua,而不是当时我已经

比较熟悉的Python和Ruby,即使它们我都关注了好几年,但是都没有Lua给我的震撼大。于是那个夏天,

稍微地尝试读了Lua的代码。

开学后,我突然觉得自己有点受唆使,轻信了动态的福音,对Lisp系以及脚本系关注太多,有点不务正业

,于是回到了C,并且在年底投入了C++。C++的模板实在是让我爱不释手,于是寒假的时候写了一个内存

分配器,用了很多模板技巧,于是渐渐地对C++也熟悉了。

到了下学期,也就是现在,经历了一个小项目之后,在放弃C++/CLI的福音转向C#后,在.NET的信仰下,

在对DLR的期待中,决心写一个Lua的DLR实现,于是我回来了。


1. 基础设施代码解读

这部分包括基本数据结构,内存管理等部分,是重头戏。

1.1. 基本数据结构

正如Brooks所说“给我看你的流程图而藏起你的表,我将仍然莫名其妙。如果给我看你的表,那么我将不

再要你的流程图,因为它们太明显了。”不理解Lua最基本的数据结构,想要理解Lua是完全不可能的。

我们从包含的Root项,即Luaconf.h开始,它给出了最基本的信息。它是基于编译器和平台,对Lua进行最

基本的设置,是程序的元数据区。

第一段,平台选择:

/*
** LUA_ANSI控制对non-ansi字符集特性的使用。
** 定义这个宏,你可以不使用non-ansi特性的使用。
*/
#if defined(__STRICT_ANSI__)
#define LUA_ANSI
#endif


#if !defined(LUA_ANSI) && defined(_WIN32)
#define LUA_WIN
#endif

#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN  /* 需要额外的库: -ldl */
#define LUA_USE_READLINE /* 需要一些额外的库 */
#endif

#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_DL_DYLD  /* 不需要额外的库 */
#endif

显然对于LUA_WIN来说,w32平台的确是用Unicode的,也就是非LUA_ANSI的。当定义了LUA_USE_LINUX和

LUA_USE_MACOSX后,需要POSIX标准以及定义相应的打开动态链接库的方法。这里可以看出Linux和BSD系

在打开动态库时的差别。

这里是POSIX的相关定义:

/*
** LUA_USE_POSIX包含了所有被标注为X/Open系统接口扩展(XSI)的功能。
** 如果你的系统兼容XSI,则定义它。
*/
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#endif

这个是环境变量相关的:

/*
** LUA_PATH和LUA_CPATH是Lua设置自己路径的环境变量名字。
** LUA_INIT是Lua检查初始化代码的环境变量名字。
** 如果你要更改名字,则自己定义。
*/
#define LUA_PATH        "LUA_PATH"
#define LUA_CPATH       "LUA_CPATH"
#define LUA_INIT "LUA_INIT"

具体路径自己定。

于是这一段也很好理解了:

/*
** LUA_PATH_DEFAULT是Lua默认的搜索Lua库的路径。
** LUA_CPATH_DEFAULT是Lua默认的搜索C库的路径。
** 如果你的机器是非传统的目录体系结构或者你要把你的库装入非传统的目录体系结构中则更改它们。
*/
#if defined(_WIN32)
/*
** 在Windows中,出现在路径中的惊叹号('!')将由当前进程的可执行文件所在的目录的路径替换
*/
#define LUA_LDIR "!//lua//"
#define LUA_CDIR "!//"
#define LUA_PATH_DEFAULT  /
  ".//?.lua;"  LUA_LDIR"?.lua;"  LUA_LDIR"?//init.lua;" /
               LUA_CDIR"?.lua;"  LUA_CDIR"?//init.lua"
#define LUA_CPATH_DEFAULT /
 ".//?.dll;"  LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"

#else
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
#define LUA_PATH_DEFAULT  /
  "./?.lua;"  LUA_LDIR"?.lua;"  LUA_LDIR"?/init.lua;" /
              LUA_CDIR"?.lua;"  LUA_CDIR"?/init.lua"
#define LUA_CPATH_DEFAULT /
 "./?.so;"  LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
#endif

好了,接下来是Lua中特别指明的平台相关部分,库的加载:

/*
** LUA_API是所有核心API的标记。
** LUALIB_API是所有标准库函数的标记。
** 如果你对函数有特殊的要求请更改它们。
** 比如你要定义一个w32 DLL要要用到核心和库函数,你可能会用到下面的LUA_BUILD_AS_DLL定义。
*/
#if defined(LUA_BUILD_AS_DLL)

#if defined(LUA_CORE) || defined(LUA_LIB)
#define LUA_API __declspec(dllexport)
#else
#define LUA_API __declspec(dllimport)
#endif

#else

#define LUA_API  extern

#endif

/* 库时常和核心一起发布 */
#define LUALIB_API LUA_API

这里的LUA_BUILD_AS_DLL就是在编译的时候提交给编译器的一个选项。下面是另外一些自定义关键字。

/*
** LUAI_FUNC是那些不要导出模块外部的extern函数。
** LUAI_DATA是那些不要导出的extern或者扩展的变量。
** 当你对它们有特殊的要求时请改变他们。当Lua被编译为共享库时,Elf/gcc(3.2或更高版本)
**会将它们标记为隐藏以优化访问
*/
#if defined(luaall_c)
#define LUAI_FUNC static
#define LUAI_DATA /* empty */

#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && /
      defined(__ELF__)
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
#define LUAI_DATA LUAI_FUNC

#else
#define LUAI_FUNC extern
#define LUAI_DATA extern
#endif

显然,一般的编译器将会标记为static,而当编译器版本为GCC 3.2+或者是ELF时,就可以使用

__attribute__((visibility("hidden"))) extern了。

/*
** LUA_QL描述了如何错误信息如何引用程序元素。
** 如果你要改变风格,请修改。
*/
#define LUA_QL(x) "'" x "'"
#define LUA_QS  LUA_QL("%s")

要理解这段代码其实也不难,随便找个程序,把这两个宏代入,比如,printf(LUA_QS, "hello world")

中,你可以得到'hello world'的输出。

/*
** LUA_IDSIZE给出了Debug模式下对函数代码的解释的最大长度。
** 如果你需要一个不同的长度,
*/
#define LUA_IDSIZE 60

一下是Lua作为一个独立程序的设置:

/*
** ===================================================================
** 独立程序配置
** ===================================================================
*/

#if defined(lua_c) || defined(luaall_c)

/*
** lua_stdin_is_tty检查标准输入是否为tty,即是否以交互模式运行Lua。
** 如果你有针对non-POSIX/non-Windows的更好的定义,请更改它。
*/
#if defined(LUA_USE_ISATTY)
#include <unistd.h>
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#include <stdio.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else
#define lua_stdin_is_tty() 1  /* assume stdin is a tty */
#endif

这里有几种选择,如果定义了LUA_USE_ISATTY,那么则使用unistd.h(POSIX标准)并将tty定义为

isatty(0),否则,检查是否为w32环境,则定义_isatty(_fileno(stdin)),再不然,用传统的Unix的习

惯,stdin的文件号(即w32中的文件句柄)为1。

提示符部分:

/*
** LUA_PROMPT是独立Lua程序的默认提示符。
** LUA_PROMPT2是独立Lua程序的默认的续行提示符。
** 如果你要用不同的提示符,请更换它们。同样你也可以通过赋值给_PROMPT/_PROMPT2动态的更改。
*/
#define LUA_PROMPT  "> "
#define LUA_PROMPT2  ">> "

程序名称:

/*
** LUA_PROGNAME独立Lua程序的默认名称。
** 如果你要用一个不同的名字或者你的系统无法自动探测名字,那么请更换它。
*/
#define LUA_PROGNAME  "lua"

/*
** LUA_MAXINPUT是Lua独立交互程序的单行最大长度。
** 如果你需要更长的行,请自行更改。
*/
#define LUA_MAXINPUT 512

/*
** lua_readline定义了如何显示提示符和从标准输入读取一行。
** lua_saveline定义了将读取的一行保存的历史中。
** lua_freeline定义了如何释放由lua_readline读取的行。
** 如果你要增强功能(比如使用GNU readline和history设施)。
*/
#if defined(LUA_USE_READLINE)
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) /
 if (lua_strlen(L,idx) > 0)  /* non-empty line? */ /
   add_history(lua_tostring(L, idx));  /* add it to history */
#define lua_freeline(L,b) ((void)L, free(b))
#else
#define lua_readline(L,b,p) /
 ((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ /
 fgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif

#endif

但是不知道为什么,它要求了Lua_State的L,但是直接将之Discard了。

再往下就是GC相关Configurations了。

/*
** LUAI_GCPAUSE以百分制定义了默认的两次垃圾收集周期的间隔时间。
** 如果你希望GC运行得更快或更慢(更大的数字意味着更长的停顿即更慢的收集)。
** 你同样也可以动态的改变该值。
*/
#define LUAI_GCPAUSE 200  /* 200% (在下次GC启动前,内存扩大一倍)*/

/*
** LUAI_GCMUL定义了默认的与相对于内存分配的垃圾收集的速度(用百分制表示)。
** 如果你要改变垃圾收集的组件的Granularity则请重新定义。(更高值意味着更慢的收集。
** 0表示无限长,每一步都是完整的收集。)你也能动态的改变。
*/
#define LUAI_GCMUL 200 /* GC以内存分配的两倍速度执行。*/

/*
** LUA_COMPAT_GETN控制了与与老版本的getn行为的兼容。
** 如果你要与Lua 5.0的setn/getn精确的兼容,请重新定义。
*/
#undef LUA_COMPAT_GETN

/*
** LUA_COMPAT_LOADLIB控制与全局loadlib的兼容性。
** 一旦你不需要全局的loadlib请将之定义为undefined。(这个函数依然以package.loadlib存在)
*/
#undef LUA_COMPAT_LOADLIB

/*
** LUA_COMPAT_VARARG控制与旧版的vararg功能的兼容性。
** 如果你的程序只使用‘...’来访问变长参数(取代旧版的arg表)。
*/
#define LUA_COMPAT_VARARG

/*
** LUA_COMPAT_MOD控制与旧版math.mod的兼容性。
** 如果你要使用math.fmod和新的%操作符来取代math.mod,请取消定义。
*/
#define LUA_COMPAT_MOD

/*
** LUA_COMPAT_LSTR控制与旧版嵌入式长字符串功能。
** 如果你要旧版的行为,请改为2,或者在使用内嵌的[[...]]时关闭错误警告请取消定义。
*/
#define LUA_COMPAT_LSTR  1

/*
** LUA_COMPAT_GFIND controls控制与旧版的string.gfind名字的兼容性。
** 如果你要将string.gfind重命名为string.gmatch,则请取消定义。
*/
#define LUA_COMPAT_GFIND

/*
** LUA_COMPAT_OPENLIB控制与旧版的luaL_openlib行为的兼容性。
** 如果你想用luaL_register来替换luaL_openLib,则取消定义。
*/
#define LUA_COMPAT_OPENLIB

/*
** luai_apicheck是Lua-C API的断言宏。
** 如果你要Lua对通过API调用获得的参数进行一些检查,请重定义luai_apicheck。
** 这个对解释器的性能有一定的影响,但是在调试与Lua交互的C代码时很有帮助。
** 用assert.h来重定义。
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(L,o) { (void)L; assert(o); }
#else
#define luai_apicheck(L,o) { (void)L; }
#endif

如果定义了这个宏,则用标准库的assert.h的assert来判断o,但是不知为什么还是抛弃了L。

/*
** LUAI_BITSINT定义了int的字节位数。
** 如果Lua不能自动探测你机器的位数,请更改这里。也许你不需要更改这里。
*/
/* 避免比较中溢出。*/
#if INT_MAX-20 < 32760
#define LUAI_BITSINT 16
#elif INT_MAX > 2147483640L
/* int has at least 32 bits */
#define LUAI_BITSINT 32
#else
#error "you must define LUA_BITSINT with number of bits in an integer"
#endif

/*
** LUAI_UINT32是32位的无符号整型。
** LUAI_INT32是32位有符号整型。
** LUAI_UMEM是足够大的用来表示Lua所使用的内存总数的无符号整数。
** LUAI_MEM是足够大的计算Lua内存使用总数的有符号整型。
** 如果你有奇特的原因默认的定义不适合你的机器。(定义在else的那部分经常起作用,
** 但是可能因64位字长浪费你机器的存储空间。)可能不不必更改这个。
*/
#if LUAI_BITSINT >= 32
#define LUAI_UINT32 unsigned int
#define LUAI_INT32 int
#define LUAI_MAXINT32 INT_MAX
#define LUAI_UMEM size_t
#define LUAI_MEM ptrdiff_t
#else
/* 16-bit ints */
#define LUAI_UINT32 unsigned long
#define LUAI_INT32 long
#define LUAI_MAXINT32 LONG_MAX
#define LUAI_UMEM unsigned long
#define LUAI_MEM long
#endif

/*
** LUAI_MAXCALLS限制了nested调用的数目。
** 如果你真的需要极深的递归调用则请自行更改。限制是任意的;
** 唯一的目的是在内存被耗尽前中止无限递归。
*/
#define LUAI_MAXCALLS 20000


/*
** LUAI_MAXCSTACK限制了C函数所能使用的Lua Stack的槽位数目。
** 如果你对C函数需要更多的Stack空间则改变它。这个限制是任意的;
** 唯一的目的是阻止C函数无止境的消耗内存空间。
*/
#define LUAI_MAXCSTACK 2048

/*
** {==================================================================
** 如果你的C Stack很小请将后续的定义值改小。(或者说你的机器有很大的C Stack,这些规定
** 对你有些死板,则你可以改大。)有些常量是控制解释器和编译器在Stack上分配内存大小的。
** 与此同时其它的限制了编译器和解释器能使用的最大的递归调用的数目。
** 当值太大时,一些深度的构造会引起C Stack的溢出。
** ===================================================================
*/


/*
** LUAI_MAXCCALLS是内嵌C调用和程序中的非中止语法内嵌的最大深度(短整型)。
*/
#define LUAI_MAXCCALLS  200


/*
** LUAI_MAXVARS是每个函数可用的局部函数的最大数目(必须小于250)。
*/
#define LUAI_MAXVARS  200


/*
** LUAI_MAXUPVALUES每个函数可使用最大的upvalues数目(必须小于250)。
*/
#define LUAI_MAXUPVALUES 60


/*
** LUAL_BUFFERSIZE是lauxlib缓存系统所使用最大缓存大小。
*/
#define LUAL_BUFFERSIZE  BUFSIZ

/* }================================================================== */

/*
** {==================================================================
** LUA_NUMBER是Lua中数的类型。
** 当且仅当如果你要用有别于double的其它数字类型来构建Lua则更改定义。
** 你也许需要更改lua_number2int和lua_number2integer。
** ===================================================================
*/

#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double

/*
** LUAI_UACNUMBER是平常的对一个数进行参数转换的的结果。
*/
#define LUAI_UACNUMBER double

/*
** LUA_NUMBER_SCAN 是读取数字的格式。
** LUA_NUMBER_FMT是写数据的格式。
** lua_number2str将一个数字转换为string。
** LUAI_MAXNUMBER2STR定义前一个转换的最大值。
** lua_str2number将string转换为数字。
*/
#define LUA_NUMBER_SCAN  "%lf"
#define LUA_NUMBER_FMT  "%.14g"
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and /0 */
#define lua_str2number(s,p) strtod((s), (p))

/*
** The luai_num*宏族定义了对数字的原操作。
*/
#if defined(LUA_CORE)
#include <math.h>
#define luai_numadd(a,b) ((a)+(b))
#define luai_numsub(a,b) ((a)-(b))
#define luai_nummul(a,b) ((a)*(b))
#define luai_numdiv(a,b) ((a)/(b))
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
#define luai_numpow(a,b) (pow(a,b))
#define luai_numunm(a)  (-(a))
#define luai_numeq(a,b)  ((a)==(b))
#define luai_numlt(a,b)  ((a)<(b))
#define luai_numle(a,b)  ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif

/*
** lua_number2int是将lua_Number转换成int的宏。
** lua_number2integer是将lua_Number转换为lua_Integer的宏。
** 如果你知道如何在你的系统中将更快的lua_Number转换成int的方法(不用取整也不抛出异常)
** 请重新定义。对于Pentium机器,原生的double到int的类型转换很慢,所以尚有一些选择值得尝试。
*/

/* 在Pentium的平台上求助于小技巧。*/
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && /
    (defined(__i386) || defined (_M_IX86) || defined(__i386__))

/* Microsoft的编译器,用汇编器。*/
#if defined(_MSC_VER)

#define lua_number2int(i,d)   __asm fld d   __asm fistp i
#define lua_number2integer(i,n)  lua_number2int(i, n)

/* 接下来的技巧应该能在Pentium的机器上运行,但有时候会因为着了DirectX的道而崩溃。*/
#else

union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) /
  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n)  lua_number2int(i, n)

#endif


/* 这个选项总是有效,但是会很慢的。*/
#else
#define lua_number2int(i,d) ((i)=(int)(d))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))

#endif

/*
** LUAI_USER_ALIGNMENT_T是类型所要求的最大的对齐。
** 如果你的系统要求大于double的对齐。(比方说,如果你的系统支持long double并且他们必须
** 16字节边界对齐,你需要加入long double到联合中。)也许你需要更改这个。
*/
#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }


/*
** LUAI_THROW/LUAI_TRY定义了Lua如何进行异常处理。
** 如果你倾向于使用longjmp/setjmp甚至是用C++,或者说如果想/不用_longjmp/_setjmp来替代
** 常规的longjmp/setjmp,请更改。默认情况下,当Lua被当作C++处理时用异常来处理错误,
** 当被要求时用_longjmp/_setjmp,否则用longjmp/setjmp。
*/
#if defined(__cplusplus)
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
#define LUAI_TRY(L,c,a) try { a } catch(...) /
 { if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int  /* dummy variable */

#elif defined(LUA_USE_ULONGJMP)
/* in Unix, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf

#else
/* default handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf

#endif

这部分是源代码级的异常处理。Unix下用_longjmp/_setjmp效率更加高。

/*
** LUA_MAXCAPTURES是在模式匹配中,一个模式最大可捕获的数目。
** 如果你想捕获更多,则更改它。该值是任意的。
*/
#define LUA_MAXCAPTURES  32


/*
** lua_tmpnam是OS库中用来创建零时名字的函数。
** LUA_TMPNAMBUFSIZE是lua_tmpnam所创建的最大名字长度。
** 如果你有tmpnam的其他选择(这个是不安全的)或者说你无论如何要原始的,请自行更改。
** 默认情况下,当POSIX有效时,Lua将会用mkstemp。
*/
#if defined(loslib_c) || defined(luaall_c)

#if defined(LUA_USE_MKSTEMP)
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
#define lua_tmpnam(b,e) { /
 strcpy(b, "/tmp/lua_XXXXXX"); /
 e = mkstemp(b); /
 if (e != -1) close(e); /
 e = (e == -1); }

#else
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e)  { e = (tmpnam(b) == NULL); }
#endif

#endif


/*
** lua_popen产生一个通过文件流与当前进程联通的新进程。
** C如果你能在你的系统里实现,请自行定义。
*/
#if defined(LUA_USE_POPEN)

#define lua_popen(L,c,m) ((void)L, popen(c,m))
#define lua_pclose(L,file) ((void)L, (pclose(file) != -1))

#elif defined(LUA_WIN)

#define lua_popen(L,c,m) ((void)L, _popen(c,m))
#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))

#else

#define lua_popen(L,c,m) ((void)((void)c, m),  /
  luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
#define lua_pclose(L,file)  ((void)((void)L, file), 0)

#endif

/*
** LUA_DL_*定义了Lua应该使用哪个动态库系统。
** 如果Lua不能在你的平台上选择正确的动态库系统(无论是Windows的DLL,还是Mac的dyld,
** 还是Unix的dlopen)。如果你的系统是Unix的一种的话,dlopen极可能存在,所以
** LUA_DL_DLOPEN将能工作。 要使用dlopen,你需要调制src/Makefile
** (可能要增加-ldl到linker的选项中),所以Lua并非自动选择。(当你对makefile增加-ldl后,
** 你必须同时增加-DLUA_USE_DLOPEN。)
** 如果你不需要任何一种动态库,请对它们取消定义。
** 默认情况下,_WIN32下是LUA_DL_DLL而MAC OS X 下是LUA_DL_DYLD。
*/
#if defined(LUA_USE_DLOPEN)
#define LUA_DL_DLOPEN
#endif

#if defined(LUA_WIN)
#define LUA_DL_DLL
#endif


/*
** LUAI_EXTRASPACE允许你向lua_State中添加用户定义的数据。
** (这些数据恰恰在lua_State指针的前面)
** 如果你当真需要这个C请定义它。这个值必须是符合你机器的最大对齐。
*/
#define LUAI_EXTRASPACE  0


/*
** luai_userstate*允许用户针对线程自定义行为。
** 如果你定义了LUAI_EXTRASPACE并且需要在线程创建/删除/继续/产生结果的时候做一些额外的事。
*/
#define luai_userstateopen(L)  ((void)L)
#define luai_userstateclose(L)  ((void)L)
#define luai_userstatethread(L,L1) ((void)L)
#define luai_userstatefree(L)  ((void)L)
#define luai_userstateresume(L,n) ((void)L)
#define luai_userstateyield(L,n) ((void)L)


/*
** LUA_INTFRMLEN是string.format中整数转换的长度更改。
** LUA_INTFRM_T是与前一个长度更改相应的整数类型。
** 如果你的机器支持long long或者说不支持long,则自行定义。
*/

#if defined(LUA_USELONGLONG)

#define LUA_INTFRMLEN  "ll"
#define LUA_INTFRM_T  long long

#else

#define LUA_INTFRMLEN  "l"
#define LUA_INTFRM_T  long

#endif

综上所述,这个文件定义的最重要的几个方面:动态库操作(重中之重,根据Programming in Lua的说法

,这方面是Lua中唯一依赖于平台的做法),异常及错误处理,打印数据格式,数字运算,C Stack,GC,

对齐等方面。

Linux下编译Lua动态库:从-fPIC到符号导出的完整实践指南 动态链接库(.so文件)是现代软件工程中实现模块化与热更新的核心技术,其核心原理在于生成位置无关代码(PIC),确保库能在内存任意地址加载。在嵌入式系统与高性能服务场景中,将脚本引擎如Lua编译为动态库,能有效实现业务逻辑热更新、减少主程序体积并提升部署灵活性。本文聚焦于Lua动态库编译的工程实践,深入解析-fPIC编译选项与-Wl,-E符号导出等关键步骤,解决编译过程中的常见陷阱,为构建轻量级、可定制的脚本运行时环境提供完整解决方案。 阅读详情

相关推荐

Linux下编译Lua动态库:从原理到实践的全流程指南

动态链接库(Dynamic Link Library,DLL)在Linux系统中以共享对象(Shared Object,.so)形式存在,是实现代码模块化、运行时加载和资源复用的核心技术。其核心原理在于通过位置无关代码(PIC)和动态符号表,允许主程序在运行时按需加载和链接库中的函数,从而实现热更新、插件化等高级特性。这一机制在需要高度灵活性和可维护性的场景中价值显著,例如为C/C++服务增加脚本化插件能力。本文聚焦于将轻量级脚本语言Lua编译为动态库的具体工程实践,深入解析了-fPIC、-shared等关

weixin_30314813的博客 408

Lua导出为外部链接库并使用

压缩包内容如下:紧接着,使用VS2022创建一个Windows桌面向导,将Lua源码压缩包内部src文件的源代码文件拷贝至VS2022创建的项目中,具体步骤如下: 将Lua源文件中str文件夹下除Makefile和luac.c文件外所有文件复制进入Project1项目路径下。src文件夹: Project1项目文件:然后进入VS2022中,添加现有项(将所有.h和.c文件都加入)。 如下:   打开luaconf.h文件,找到第244行,如下  赋值上述红框中的宏,添加至项目–>属性–>C/C+±->预处理

田螺姑娘的博客 2351

游戏逆向实战:通过Hook技术动态提取运行时Lua脚本源码

在软件安全分析和游戏逆向工程领域,Hook技术是一种关键的动态分析手段,它通过拦截和修改程序执行流程来实现对目标行为的监控与干预。其核心原理是在程序运行时,将特定函数调用重定向到自定义代码,从而在不修改原始二进制文件的情况下,实现对内存数据、函数参数和返回值的捕获与处理。这项技术在漏洞挖掘、协议分析、游戏逻辑研究等方面具有重要价值。以游戏开发为例,许多游戏使用Lua等脚本语言驱动核心逻辑,但发布时会对脚本进行加密或编译以保护知识产权。此时,通过Hook Lua虚拟机加载函数(如luaL_loadbuffer

weixin_34301132的博客 289

lua源码编译linux,LUA源码之luaconf.h

Luaconf.h是配置的总集,定义了平台相关的设置,是所有文件都包含的,即RootlyIncluded。0. 前言开始关注Lua也是06年六月的事情,《程序员》的2006年第六期中,我独独看中了Lua,而不是当时我已经比较熟悉的Python和Ruby,即使它们我都关注了好几年,但是都没有Lua给我的震撼大。于是那个夏天,稍微地尝试读了Lua的代码。开学后,我突然觉得自己有点受唆使,轻信了动态的...

weixin_29552815的博客 629

C++项目工程化实战:gflags配置管理与gtest单元测试框架详解

在C++项目开发中,配置管理和代码测试是构建健壮、可维护软件的核心工程实践。配置管理涉及程序运行时参数的动态调整,传统硬编码或手写解析器的方式在项目复杂度提升时难以维护。单元测试作为软件质量的‘安全带’,通过自动化验证代码逻辑,能有效预防回归错误并充当活文档。gflags库采用声明式参数定义,自动处理命令行解析、类型检查和帮助生成,极大简化了配置管理。gtest框架提供了丰富的断言宏、测试夹具和模拟对象支持,使编写结构化、可维护的测试用例变得高效。这两个库协同工作,为C++项目提供了标准的配置与测试基础设施

weixin_33912453的博客 620

luaconf:luaconf 是一个 C 库,用于解析用 lua 编写的配置文件

名称 luaconf - 用于解析用 lua 编写的配置文件的 C 库。 地位 该模块尚未发布。 概要 /* -- conf.lua site1 = { ['domain'] = 'www.taobao.com', ['level'] = 6, } */ # include " luaconf.h " int main ( int argc, char *argv[]) { long n; size_t size; luaconf_inst *inst; luaconf_elt *elt1; luaconf_elt *elt2; char buf[ 1024 ]; inst = luaconf_init

编译Lua库并配置开发环境

作者: Apex 发表于 2006-10-21 要在自己的程序中使用Lua,我们必须将Lua解释器核心编译到自己的程序中来,无论是直接编译到主程序中,还是作为外部DLL调用,总之,第一件事情是编译Lua解释器核心。说明:以后的操作如果没有特别注明,就是在Windows平台上进行的。首先,到Lua官方网站下载最新的Lua源代码,得到的是一个.tar.gz。可以用流行的压缩软件如Win

zhangmiaoping23的专栏 3844

lua-conf:将lua表转换为C对象,并在许多lua状态之间共享

什么是lua-conf lua-conf是一个lua库,它可以将一个lua表转换为一个常量C对象(一个lightuserdata)。 然后,您可以在许多lua状态之间共享它。 为什么要使用lua-conf 读取常量C对象是线程安全的,因此您可以在许多lua状态中同时使用它。 如果转换大型lua表,则将减少lua vm的内存使用量。 因此,垃圾收集器将运行得更快(标记更少的gc对象)。 有时您需要重新加载lua vm,表中的常量数据不再需要解析器。 支持的类型 键必须是32位整数或字符串,值可以是布尔值,字符串,数字和表。 如何建造 在项目中包含源luaconf.c,或将其构建为动态库。 gcc -O2 -Wall --shared -o conf.so luaconf.c #linux gcc -O2 -Wall --shared -o conf.dll luaconf.c

C++Builder 编译 Lua 库方法

编译静态库:新建一个LIBRARY的静态库工程,然后把SRC目录下的*.c和*.h复制到工程目录中不需要lua.c luac.c lua.hpp三个文件,把*.c加入到工程中,*.h加不加入都无所谓,设置一下工程属性,主要是RELEASE一下然后编译,就会生成LIB文件动态库编译:新建一个DLL工程,然后把SRC目录下的*.c和*.h复制到工程目录中不需要lua.c luac...

weixin_33770878的博客 315

高阶玩法——Dify生成的数据自动写入mysql数据库

采用自定义工具方式,利用 python编写一个服务sql_save_post,将接收到的内容写入指定数据库的表中,并为该服务撰写一个 OpenAPI 的 schema。配置工作流:我们以写入天气预报为例,在生成天气预报内容后,连接自定义工具“sql_save_post”,将所需的字段配置完成后,实现将生成的内容自动写入mysql数据库中。编写OpenAPI的schema:在dify平台的工具栏目,创建自定义工具,输入工具名称“sql_save_post”。工具:sql_save_post;

qq_44493378的博客 8541

SimpleFOC STM32实战:基于F103与HAL库,剖析速度环与电流环的协同控制

本文详细介绍了基于STM32F103与HAL库的SimpleFOC实战应用,重点剖析速度闭环控制与电流环的协同工作原理。通过开发环境搭建、参数调试技巧及性能优化方案,帮助开发者高效实现无刷电机精准控制,适用于机器人、无人机等高精度应用场景。

weixin_29170327的博客 477

Linux下编译Lua生成动态库:从原理到实践的全流程指南

动态链接库(.so文件)是Linux系统中实现代码复用、模块化设计和插件化架构的核心技术。其原理在于编译时生成位置无关代码(PIC),运行时通过动态链接器加载,从而实现多个进程共享同一份库代码,显著节省内存并支持热更新。在嵌入式开发、游戏引擎或需要轻量级脚本集成的C/C++项目中,这种技术价值尤为突出。Lua作为一种高效、小巧、易于嵌入的脚本语言,常被选为“胶水语言”嵌入主程序。通过将其编译为动态库而非静态库,开发者可以实现运行时动态加载不同的Lua模块,构建灵活的插件系统。本文聚焦于**Lua动态库编译*

weixin_30698527的博客 345

NET 实战:30 天搞定企业级 Web 订餐系统(附完整源码 + 数据库设计)

订餐流程:浏览菜品 → 选择菜品及数量 → 填写送餐地址 → 提交订单 → 数据库记录核心代码(绑定菜品列表):vb' 绑定菜单表到DataGrid控件,展示菜品信息user id=sa;' 查询菜品名称、价格、口味Dim adpt1 As New SqlDataAdapter("select cdishid,vdishname 菜品名称,cdishrate 价格,vdishdescription 口味 from dish", conn)End Sub用户体验优化。

m0_67740236的博客 1517

LuaJIT完全指南:如何通过即时编译将Lua性能提升100倍?

LuaJIT作为Lua语言的即时编译器实现,能够将标准Lua代码的执行速度提升数十倍甚至上百倍,是游戏开发、嵌入式系统和性能敏感应用的首选方案。本文将深入解析LuaJIT的完整安装流程、多平台编译技巧以及实际部署的最佳实践,帮助开发者充分利用这一强大的性能优化工具。 ## 📊 LuaJIT架构概览与技术优势 在开始安装之前,了解LuaJIT的核心架构有助于更好地配置和使用它。LuaJIT采用

gitblog_00512的博客 652

wsl2上运行带有Isaac Gym的程序报错: GPU Pipeline: disabled

显示GPU Pipeline:disabled,查找相关文档发现是WSL2目前不支持Isaac Gym,时,想要在wsl2上运行,最后报错如下。

2303_78660611的博客 957

电赛MSP430F5529之超声波测距+OLED 显示(含主要代码)

目录 前言 一、超声波介绍 二、部分代码 三、总结 题外话: 前言 哎,又双叒叕,电赛延期了,看起来像是遥遥无期,但是肯定要考虑大局,大家就继续抓紧时间学习知识,巩固自己的知识,更进一步。好了,今天主要是继承上一篇博文(OLED显示)写的,主要是写超声波测距的(US-015) 一、超声波介绍 利用TI公司的MSP430F5529单片机+超声波模块+OLED 实现 这里主要是利用单片机定时器的捕获功能来捕获超声波高电平持续时间,再计算得到距离,最后再在OLED 屏幕上显示出来,上图

不说二话的自家人的博客 1万+

Cocos lua 堆栈信息中路径太长被截取问题解决办法

此方法需要修改 lua 虚拟机实现,但是只需要修改一个宏定义即可。 打开 cocos2d-x-3.10/external/lua/lua/luaconf.h 找到 LUA_IDSIZE 定义,将其值 60 改为需要的值,例如 200 重新编译项目/运行游戏即可。 说明:这个宏控制 debug 信息中的路径信息的最大字符数,所以改大一些就能显示更长的路径。 ...

Hustlion 的技术博客 1129

ClickHouse集群扩容实战:用clickhouse-copier搞定数据迁移与分片重平衡

本文详细介绍了使用clickhouse-copier工具实现ClickHouse集群从3分片到5分片的平滑扩容实战。通过分片级并行处理、原子性保证等核心机制,该工具能高效完成数据迁移与分片重平衡,同时保持服务连续性。文章涵盖集群拓扑规划、表结构检查、迁移配置、执行监控及迁移后优化等关键步骤,为大数据量场景下的ClickHouse扩容提供完整解决方案。

weixin_29091837的博客 294

lua中自定义加载lua的path

有两个方法: 一种方法是在lua源码中扩展宏: #define LUA_PATH_DEFAULT \ LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" "E:\\OGL5\\c++calllua\\luascript\\?.lua;" \ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ ".\\?.lua;" ".\\?\\i

小孔明的专栏 2201

054_小驰私房菜_Camx i2c读写相关备忘

Camera 对Ae、Af这些控制,实际都是,最终实际都是落实到hal下发相关的指令给驱动,那hal这边是怎么给驱动下发相关命令的呢?#小驰私房菜054# #Qcom Camx#可以参考看下下面相关代码内容。

149

SOEM主站开发篇(1):移植SOEM主站到Linux开发板

详细介绍了SOEM主站源码移植到Linux开发板上的步骤,同时演示了如何使用Linux开发板获取EtherCAT从站的PDO映射信息。

kevin1499的博客 2398

lua绝对路径linux,Lua路径

在学习的路上踩坑不止,今天遇到这个坑是关于“路径”的。在windows版本中,lua默认的路径包括当前路径,以及当前路径下的lua子目录。因此测试时,理所当然将所有lua文件都放在当前目录的lua子目录下。切换到linux系统(debian 8),发现lua默认没有当前lua子目录。当然,可以修改lua文件,在require语句中明确增加lua来规避,例如以下语句:local fsm = requ...

weixin_33305287的博客 1656

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

lua.h源码详解

/* ** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this fil

活在阳光下 2577

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Lua的require使用

一.require的作用 1. 加载指定的模块,相当与#include作用类似,加载了该模块,那么就可已使用模块中的全局函数和全局数据(如表等等) 注:实际上require “xxx”后,会将xxx中的全局函数和数据放到表_G中,所以也就能访问了。2.例子(1)main.lua require "test" require "showSome"(2)test.lua function C

和尚的专栏 5万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Lua 快速入门(四)——多脚本执行

lua系列之多脚本执行

qq_41044598的博客 2894

linux下popen函数用法代码

linux下popen函数用法代码 // linux下popen函数用法代码:zread.c,摘自gzip例子 #include <stdio.h> #include <stdlib.h> #include <string.h> /* Trivial example of reading a gzip'ed file or gzip'ed standard input * using stdio functions fread(), getc(), etc.

abc 452
上一篇: Lua 5.1.1 源代码阅读笔记:
下一篇: Lua源码分析(1)
skyremember
博客等级 码龄20年 204粉丝 484原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值