第二节 Lua1.0源码小分析

引言

上面第1节,概要介绍了Lua1.0源代码的编译和执行过程,下面就让我们来看看真正的源代码吧。

main函数你在哪里?

任何一个可执行的程序都有一个main函数,那lua的main函数在哪里呢?在lua.c里面。

/*
** lua.c
** Linguagem para Usuarios de Aplicacao
** TeCGraf - PUC-Rio
** 28 Apr 93
*/

#include <stdio.h>

#include "lua.h"
#include "lualib.h"

int main (int argc, char *argv[])
{
 int i;
 if (argc < 2)
 {
  puts ("usage: lua filename [functionnames]");
  return 0;
 }

 iolib_open ();
 strlib_open ();
 mathlib_open ();
 lua_dofile (argv[1]);
 return 0;
}

上面代码和原来默认下载的代码不一样,原因是我删掉了那些没用的干扰片段。我们从上面的代码可以看出main函数的主要操作有

  1. 检测参数是否符合要求
  2. 打开iolib, iolib_open() 这个主要作用是提供lua的对文件操作的函数
  3. 打开strlib,strlib_open() 这个主要作用是提供lua的对字符串操作的函数
  4. 打开mathlib, mathlib_open() 这个主要作用是提供了lua的一些数学函数
而最关键的一句是
lua_dofile (argv[1]);

这行代码是真正开始打开lua脚本文件,分析词法,语法和执行的语句。

现在我们简单介绍一下lua和c语言的相互操作
在c语言中,为了提供一个lua中可以执行的函数,首先必须得定义这个函数,然后使用lua_register来注册这个函数,这是一个宏。定义如下
#define lua_register(n,f)	(lua_pushcfunction(f), lua_storeglobal(n))

这里我们看是lua_register实际上等于执行了两个函数操作lua_pushcfunction(f)和lua_storeglobal(n)。任何一个c函数都必须具有lua_CFunction的类型。然后才能够被lua注册,而后一个函数,则是将该c函数的参数入栈。

我们看到了lua_register的时候,不妨想想,既然如此,我们是否可以自己写个函数,然后注册给lua呢?最后在脚本中验证一下?
OK,可以的,让我们试试吧。捡简单的strlib来试试。在strlib.c文件中添加如下的函数
/**
Find the index of first occurance of sub_str from the right side
index=strrfind(str,sub_str)
*/
static void str_rfind(void)
{
	int n;
	char *s1,*s2;
	lua_Object o1=lua_getparam(1);
	lua_Object o2=lua_getparam(2);
	if(!lua_isstring(o1) || !lua_isstring(o2))
	{
		lua_error("incorrect arguments to function `strfind'");
		return;
	}
	s1=lua_getstring(o1);
	s2=lua_getstring(o2);
	n=strlen(s1)-(strstr(s1,s2)-s1);
	lua_pushnumber(n);
}


/**
    Find the character at position index
	ch=strat(str,index)
*/

static void str_at(void)
{
	char *s;
	int index;
	lua_Object o1=lua_getparam(1);
	lua_Object o2=lua_getparam(2);
	if(!lua_isstring(o1))
	{
		lua_error("incorrent arguments to function `strat'");
		return;
	}
	s=strdup(lua_getstring(o1));
	index=lua_getnumber(o2);
	if(index>strlen(s)){
		lua_error("index out of bound error to function `strat'");
		return;
	}
	s[index]=0;
	lua_pushstring(&s[index-1]);
	free(s);
}
/**
check whether the string ends with sub_str
bool result=strendswith(str,sub_str)
*/
static void str_ends_with(void)
{
	char *s1,*s2;
	char *s1_sub;
	lua_Object o1=lua_getparam(1);
	lua_Object o2=lua_getparam(2);
	int str_from_index=0;
	int sub_len=0;
	if(!lua_isstring(o1) || !lua_isstring(o2))
	{
		lua_error("incorrect parameters to function `strendswith`");
		return;
	}
	s1=strdup(lua_getstring(o1));
	s2=strdup(lua_getstring(o2));
	sub_len=strlen(s2);
	str_from_index=strlen(s1)-sub_len;
	s1_sub=s1+str_from_index;
	if(strcmp(s1_sub,s2)==0)
	{
		lua_pushnumber(1);
	}
	else
	{
		lua_pushnil();
	}
	free(s1);
	free(s2);
}

然后在strlib_open函数中注册这三个函数
 lua_register("strrfind",str_rfind);
 lua_register("strat",str_at);
 lua_register("strendswith",str_ends_with);

好了,编译吧。。。

脚本如下

a="apple"
print(strat(a,4))
print(strrfind(a,"pp"))
print(strendswith(a,"le"))

看看输出结果吧。。。是不是正确的。

重要事项:Lua的索引是从1开始的,不是从0,各位亲注意了。。。

版权所有,保留所有权利。

你可能感兴趣的:(源码,lua)