参考lua源码5.1.4版本源码
min.c文件:
/*
* min.c -- a minimal Lua interpreter
* loads stdin only with minimal error handling.
* no interaction, and no standard library, only a "print" function.
*/
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
static int print(lua_State *L)
{
int n=lua_gettop(L);
int i;
for (i=1; i<=n; i++)
{
if (i>1) printf("\t");
if (lua_isstring(L,i))
printf("%s",lua_tostring(L,i));
else if (lua_isnil(L,i))
printf("%s","nil");
else if (lua_isboolean(L,i))
printf("%s",lua_toboolean(L,i) ? "true" : "false");
else
printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
}
printf("\n");
return 0;
}
int main(void)
{
lua_State *L=lua_open();
lua_register(L,"print",print);
if (luaL_dofile(L,NULL)!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));
lua_close(L);
return 0;
}
由这个我呢间可知,可以使用lua_register()函数来使得lua可以使用C++定义的内部函数。
函数格式必须为static int , 其中int是指返回值个数。
lua脚本:
openHandle()
wr(0x0000, 1, "data.dat", 0)
wr(0x1000, 1, "data.dat", 512)
wr(0x0010, 1, "$mem", 0) -- 将内存中的数据写入磁盘
wr(0x2000, 1, "data.dat", 1024)
rd(0x0000, 1, "rdata.dat",0)
rd(0x1000, 1, "rdata.dat",512)
rd(0x2000, 1, "$mem",512) -- 将从磁盘读出的数据写入内存
rdmem(512,512,"rdata.dat",1536) -- 将内存中的数据写入文件,参数含义为:内存偏移,数据大小(字节),文件路径,文件偏移
slp(1000)
randomseed(3) -- 初始化随机数种子
x=random() -- 生成一个0-1之间的随机数
y=random(10,100) -- 生成一个10-100之间的随机数
z=random(10) -- 生成一个1-10之间的随机数
printf('123,x=%0.3f, y=%d, z=%d,%s,%c\n',x,y,z,'Hello word','A') -- 打印函数
wr(0x3000, 1, "data.dat", 1536)
rd(0x3000, 1, "rdata.dat", 1024)
cmp("$mem",512,"$mem",1024,1) -- 比较 512,1024为偏移,1为sector.$mem 的位置可以是内存或文件
closeHandle()
MFC对应的函数:
// print函数实现
int CRunLuaDlg::luaPrintf(lua_State *L)
{
int n = lua_gettop(L);
if(!lua_isstring(L,1))
{// 如果第一个参数不是string类型,则报参数错误
g_lpWnd->AddLog(_T("printf arguarement invalid!\n"));
return 0;
}
const char* fmt = lua_tostring(L,1);
CArgList argList;
for(int i=2;i<=n;i++)
{
int nType = lua_type(L,i);
switch (nType)
{
case LUA_TNUMBER: // double
{
double x = lua_tonumber(L,i);
argList.AddArgu(x);
}break;
case LUA_TSTRING: // string
{
const char *str = lua_tostring(L,i);
argList.AddArgu(str);
}break;
case LUA_TBOOLEAN: // boolean
{
BOOL bVal = lua_toboolean(L,i);
argList.AddArgu((BOOL)bVal);
}break;
}
}
char strfmt[512] = { 0 };
g_lpWnd->FmtDecode(fmt,&argList,strfmt);
TRACE(strfmt);
g_lpWnd->AddPrint(strfmt);
char lpstrlog[530] = { 0 };
sprintf_s(lpstrlog,530,"add print:\"%s\"\n",strfmt);
g_lpWnd->AddLog(lpstrlog);
return 0;
}
// 设置随机数种子
int CRunLuaDlg::luaRandomSeed(lua_State *L)
{
int n = lua_tointeger(L,1);
srand(n);
CString strMsg;
strMsg.Format(_T("srand(%d)\n"),n);
g_lpWnd->AddLog(strMsg);
return 0;
}
// 返回随机数
int CRunLuaDlg::luaRandom(lua_State* L)
{
CString strMsg;
int argn = lua_gettop(L);
if(argn == 0) // 返回0到1之间的随机数
{
double dx = (rand()%10000)*1.0/10000;
lua_pushnumber(L,dx);
strMsg.Format(_T("gen random num:%f\n"),dx);
g_lpWnd->AddLog(strMsg);
}
else if(argn == 1) // 返回1 - n之间的整数
{
int n = lua_tointeger(L,1);
int nx = 1+rand()%n;
lua_pushinteger(L,nx);
strMsg.Format(_T("gen random num:%d\n"),nx);
g_lpWnd->AddLog(strMsg);
}
else // 返回n-m之间的随机整数
{
int n = lua_tointeger(L,1);
int m = lua_tointeger(L,2);
int nx = n + rand()%(m-n);
lua_pushinteger(L,nx);
strMsg.Format(_T("gen random num:%d\n"),nx);
g_lpWnd->AddLog(strMsg);
}
return 1;
}
// 写数据到磁盘
int CRunLuaDlg::luaWrite(lua_State *L)
{
DWORD dwAddr = lua_tointeger(L,1);
DWORD dwSecNum = lua_tointeger(L,2); // Sect
const char *lpchFile = lua_tostring(L,3);
DWORD dwOffset = lua_tointeger(L,4); // Byte
CString strMsg;
BOOL bRet = TRUE;
DWORD dwBytes = dwSecNum * 512;
LPBYTE lpBuff = new BYTE[dwBytes];
ZeroMemory(lpBuff, dwBytes);
if(strcmp(lpchFile,"$mem") == 0) // 从内存读数据
{
strMsg.Format(_T("write mem data to disk (mem offset=%d, sect num=%d, addr=0x%X):"),
dwOffset,dwSecNum,dwAddr);
TRACE(strMsg);
g_lpWnd->AddLog(strMsg);
// 判断是否越界
if(g_lpWnd->m_lpMemBuff == NULL || (g_lpWnd->m_dwMemSize-dwOffset) < (dwSecNum*512))
{
strMsg = _T(" Memmory out of boudary!");
g_lpWnd->AddLog(strMsg);
TRACE(strMsg);
bRet = FALSE;
}
else
{
memcpy(lpBuff,g_lpWnd->m_lpMemBuff+dwOffset,dwSecNum*512); // 将内存中的数据拷贝到buff中
}
}
else // 从文件读数据
{
LPWSTR lpwstrPath = AnsicToUnicode(lpchFile);
strMsg.Format(_T("write file data to disk (file name=%s, data offset=%d, sect num=%d, addr=0x%X):"),
lpwstrPath,dwOffset,dwSecNum,dwAddr);
g_lpWnd->AddLog(strMsg);
TRACE(strMsg);
CFile file;
if(!file.Open(lpwstrPath,CFile::modeRead | CFile::shareDenyNone))
{// 打开文件失败
CString strLog;
strLog.Format(_T(" failed to open file %s . err code=%d."),lpwstrPath,GetLastError());
g_lpWnd->AddLog(strLog);
TRACE(strLog);
bRet = FALSE;
}
if(bRet)
{
file.Seek(dwOffset, CFile::begin);
DWORD dwReadBytes = file.Read(lpBuff,dwBytes);
file.Close();
}
if(lpwstrPath)
delete[] lpwstrPath;
}
// 将数据写入磁盘
int nLoop = (dwSecNum+127)/128;
for(int i=0;i<nLoop && bRet;i++)
{
int _nSectCnt = 128;
if((dwSecNum - i * 128) < 128)
_nSectCnt = dwSecNum%128;
if(!WriteSectors(g_lpWnd->m_hFile, dwAddr+i*128, lpBuff +i*128*512, _nSectCnt))
{
strMsg.Format(_T(" write data to disk fail! (disk addr:0x%X, buff offset:%d, sect cnt:%d, err code=%d)."),
dwAddr+i*128, i*128*512, _nSectCnt, GetLastError());
g_lpWnd->AddLog(strMsg);
TRACE(strMsg);
bRet = FALSE;
break;
}
}
strMsg = bRet?_T("\tdone\n"):_T("\tfail\n");
TRACE(strMsg);
g_lpWnd->AddLog(strMsg);
if(lpBuff)
delete[] lpBuff;
return 0;
}
// 从磁盘读取数据
int CRunLuaDlg::luaRead(lua_State *L)
{
DWORD dwAddr = lua_tointeger(L,1);
DWORD dwSecNum = lua_tointeger(L,2);
const char* lpchData = lua_tostring(L,3);
DWORD dwOffset = lua_tointeger(L,4);
DWORD dwBytes = dwSecNum * 512;
LPBYTE lpBuff = new BYTE[dwBytes];
ZeroMemory(lpBuff, dwBytes);
if(strcmp(lpchData,"$mem") == 0)
{ // 如果是从内存读数据
char szMsg[512] = { 0 };
sprintf_s(szMsg,512,"read disk data to mem (disk addr=0x%X, sect num=%d, mem offset=%d):",
dwAddr, dwSecNum, dwOffset);
TRACE(szMsg);
g_lpWnd->AddLog(szMsg);
}
else
{ // 如果是从文件读数据
char szMsg[512] = { 0 };
sprintf_s(szMsg,512,"read disk data to file (disk addr=0x%X, sect num=%d, file offset=%d, file name=%s):",
dwAddr, dwSecNum, dwOffset, lpchData);
TRACE(szMsg);
g_lpWnd->AddLog(szMsg);
}
BOOL bRet = TRUE;
/***** 从Sector读取数据 *****/
int nLoop=(dwSecNum+127)/128;
for(int i=0;i<nLoop && bRet;i++)
{
int _nSectCnt = 128;
if((dwSecNum - i * 128) < 128)
_nSectCnt = dwSecNum%128;
if(!ReadSectors(g_lpWnd->m_hFile, dwAddr + i * 128, lpBuff+(i * 128)*512, _nSectCnt))
{
char szMsg[512] = { 0 };
sprintf_s(szMsg,512," read data from disk fail! (disk addr=0x%X, buff offset=%d, sect cnt=%d, err code=%d).",
dwAddr+i * 128,(i * 128)*512,_nSectCnt,GetLastError());
TRACE(szMsg);
g_lpWnd->AddLog(szMsg);
bRet = FALSE;
break;
}
}
/**/
if(bRet)
{// 读取数据无误
CString strMsg;
if(strcmp(lpchData,"$mem") == 0) // 将数据写入内存
{
if(g_lpWnd->m_lpMemBuff == NULL || (g_lpWnd->m_dwMemSize-dwOffset) < (dwSecNum*512)) // 判断内存是否足够
{
strMsg.Format(_T(" Mem buffer too small!"));
g_lpWnd->AddLog(strMsg);
TRACE(strMsg);
bRet = FALSE;
}
else
{
memcpy(g_lpWnd->m_lpMemBuff+dwOffset,lpBuff,dwSecNum*512); // 将数据拷贝到内存中
}
}
else // 将数据写入文件
{
LPWSTR lpwstrPath = AnsicToUnicode(lpchData);
CFile file;
if(!file.Open(lpwstrPath,CFile::modeCreate | CFile::modeNoTruncate |CFile::modeReadWrite | CFile::shareDenyNone))
{
CString strErr;
strErr.Format(_T(" Failed to open file %s, err code=%d."),lpwstrPath,GetLastError());
TRACE(strErr);
g_lpWnd->AddLog(strErr);
bRet = FALSE;
}
if(bRet)
{
file.Seek(dwOffset, CFile::begin);
file.Write(lpBuff,dwBytes);
file.Close();
}
if(lpwstrPath)
delete[] lpwstrPath;
}
}
g_lpWnd->AddLog(bRet?_T("\tdone\n"):_T("\tfail\n"));
TRACE(bRet?_T("\tdone\n"):_T("\tfail\n"));
if(lpBuff)
delete[] lpBuff;
return bRet;
}
// 延时
int CRunLuaDlg::luaSleep(lua_State *L)
{
int nDelay = lua_tointeger(L,1);
CString strMsg;
strMsg.Format(_T("Sleep %dms...\n"),nDelay);
g_lpWnd->AddLog(strMsg);
TRACE(strMsg);
Sleep(nDelay);
return 0;
}
// 打开句柄
int CRunLuaDlg::luaOpenHandle(lua_State *L)
{
CString strMsg;
if(!g_lpWnd->OnOpenDisk())
{
strMsg.Format(_T("open handle failed, err code=%d\n"),GetLastError());
g_lpWnd->AddLog(strMsg);
}
else
{
strMsg = _T("open handle\n");
g_lpWnd->AddLog(strMsg);
}
return 0;
}
// 关闭句柄
int CRunLuaDlg::luaCloseHandle(lua_State *L)
{
if(g_lpWnd->m_hFile)
{
CloseHandle(g_lpWnd->m_hFile);
g_lpWnd->m_hFile = NULL;
}
CString strMsg = _T("close handle\n");
g_lpWnd->AddLog(strMsg);
return 0;
}