MFC lua编程之lua函数作为MFC内部函数调用

参考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;
}
相关文章
相关标签/搜索