QT上位机开发(内嵌虚拟机的软件开发)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        不知道大家有没有玩过plc设备。plc设备从本质上来说,就是一个单片机设备,只不过它的电源、输入、输出做了很多的加强措施。但是从功能说,plc又不是一个简单的io设置,好像只需要设置一个高低电平就可以了。所以使用plc的人,要想把plc用的好,让plc用在更多的场景上面,仅仅会接线是不够的,他还要知道怎么编写梯形图,或者知道怎么编写脚本。

        这就我们一个启示。如果我们的上位机只是简单的应用,那么功能就不需要设置地很复杂。但是一旦大家希望把自己的上位机部署到更多的场景当中,那么不管怎么开发,都不一定能满足特定场景的需要。这个时候就有必要在上位机当中嵌入一个虚拟机脚本软件,这一点就非常重要了。某种意义上来说,这相当于给你的上位机赋予了第二次生命,软件本身有了更广阔的发展舞台,而不仅仅是我们提供什么,客户就只能做什么。今天呢,我们正好借助于lua语言,看看怎么在上位机当中嵌入一个虚拟机。

1、创建一个基础widget工程

        创建这个widget工程的目的仅仅是为了演示,其实纯console工程也是可以的。

2、下载lua

        既然vs支持nuget下载,那么除了c# wpf之外,我们也可以用nuget下载一下lua第三方包。输入lua,寻找到第一个选项即可,十分方便。目前下载的版本是5.4.6,还算是比较新的版本。

QT上位机开发(内嵌虚拟机的软件开发)_第1张图片

3、增加lua调用c的函数

        如果是lua调用c,那么需要利用lua_register注册一个函数。这个函数最好用extern "C"包起来,这样保证链接没有问题。当然,我们为了方便测试,直接把lua_State虚拟机变量放在了外面。

#include 
using namespace std;

#include 
#include 

#include "lua.hpp"
#include "QtWidgetsApplication.h"

// static variable
static lua_State* L = NULL;

// lua call c
extern "C" int exampleFunction() {
	const char* arg = lua_tostring(L, 1); 
	qDebug()<< "C++ function called with argument: " << arg ;
	return 0; 
}

void registerFunction(const QString& functionName, lua_CFunction function) {
	lua_register(L, functionName.toUtf8().constData(), function);
}

bool executeScript(const QString& script) {
	int result = luaL_dostring(L, script.toUtf8().constData()); 
	return (result == LUA_OK);
}

4、c调用lua函数

        如果是c调用lua函数,那么需要一开始利用luaL_dofile加载一下lua文件。文件中因为只有函数,所以等于没执行。注意lua文件要和cpp文件在同一层级的目录下。加载好了之后,就可以利用lua_pcall进行加载和处理了。

// c call lua
bool loadLuaScript(const QString& filePath) {
	int result = luaL_dofile(L, filePath.toUtf8().constData());
	return (result == LUA_OK);
}

void callLuaFunction(const QString& functionName, const QString& arg) {
	lua_getglobal(L, functionName.toUtf8().constData()); 
	lua_pushstring(L, arg.toUtf8().constData());          
	lua_pcall(L, 1, 0, 0);                                
}

        其中LuaScript.lua内容如下所示,

-- LuaScript.lua
function luaFunctionFromCpp(arg)
    print("Lua function called from C++ with argument: " .. arg)
	---os.execute('mkdir 456')
end

5、测试和准备

        前面虽然也写了lua调用c,以及c调用lua,但是怎么测试没有讲。这部分呢,其实不复杂。首先我们创建一个lua虚拟机,接着先测试lua调用c,然后测试c调用lua,最后删除lua虚拟机。整个test测试函数可以放在main函数的任何一个位置。

static void test()
{
	// create a vm
	L = luaL_newstate();
	luaL_openlibs(L);

	// lua call c
	registerFunction("exampleFunction", (lua_CFunction)&exampleFunction);
	executeScript("exampleFunction('Hello from Lua!')");

	// c call lua
	loadLuaScript("./LuaScript.lua");
	callLuaFunction("luaFunctionFromCpp", "Hello from C++!");

	// close vm
	lua_close(L);
}

        最后有一点需要注意下,如果是lua调用c还比较好测试,直接在c函数设置断点,就能判断有没有调用成功。如果是c调用lua,可以通过在lua文件创建目录,或者生成文件的方法,来判断lua函数是不是真得执行到了。这一点可以参考上述lua文件中被注释掉的内容。

你可能感兴趣的:(C#,WPF,+,QT上位机开发,qt,junit,开发语言)