LUA语言与西门子PLC通过S7通信交互数据(二、自制lua协议库即lua与C语言交互)

衔接上篇,本文分为几个内容:
1、使用VS新建一个动态链接库。
2、移植lua协议库。
3、在协议库内编写Add(加法函数)并验证,这实验用来说明lua与C如何直接进行变量交互。
4、在协议库内编写byte解析成位函数并验证,这实验用来说明lua与C如何通过数组进行交互。
5、在协议库内编写lua协议栈打印函数,方便对协议库的调试。

以下具体说明如何操作:
一、使用VS新建一个动态链接库
操作步骤1:文件----新建项目,项目名称为testlua
在这里插入图片描述
操作步骤2:
在这里插入图片描述
操作步骤3:
在这里插入图片描述
操作步骤4:
在这里插入图片描述

操作步骤5:
找到下载的在这里插入图片描述解压开并复制,lua-5.1.4文件夹下,src文件夹。
操作步骤6:
复制src文件夹到新建的testlua项目根目录,并改src文件夹名为luasrc,如下图所示:
在这里插入图片描述
二、移植lua协议库。
操作步骤1:
添加luasrc文件夹下.c与.h文件到项目内。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
操作步骤2:
修改头文件包含目录。
在这里插入图片描述

操作步骤3:
修改输出文件名,这个文件名要和l协议内注册的函数库名一致,这个后面会详细说明。
修改
操作步骤4:
编译一次,会出现以下错误,解决方案是移除luac.c文件。
在这里插入图片描述
在这里插入图片描述
操作步骤5:
再次编译一次,出现生成成功提示,没有错误报警,就已经移植成功了。
在这里插入图片描述
三、在协议库内编写Add(加法函数)并验证,这实验用来说明lua与C如何直接进行变量交互
操作步骤1:
添加以下代码到main.cpp文件内,并编译。

extern "C" {
#include "lua.h"  
#include "lualib.h"  
#include "lauxlib.h"
};
#include <iostream>  
using namespace std;
//定义加法函数
extern "C" int Add(lua_State* L) 
{
    double op1 = luaL_checknumber(L,1); //取出lua调用Add函数时传递的第一个参数
	double op2 = luaL_checknumber(L,2); //取出lua调用Add函数时传递的第二个参数
	lua_pushnumber(L,op1+op2); //把结果压入lua栈
    return 1;   //返回结果
}
static luaL_Reg mylibs[] =     //把Add函数注册
{ 
    {"Add", Add},
    {NULL, NULL} 
};
extern "C" __declspec(dllexport)
int luaopen_mylib(lua_State* L)    //注意“luaopen_mylib”函数名内的“mylib”,要与输出的文件名一致
{
    const char* libName = "mylib";//注意"mylib",要与输出的文件名一致
    luaL_register(L,libName,mylibs);
    return 1;
}

操作步骤2:
复制生成的mylib.dll文件到C:\Program Files (x86)\Lua\5.1\clibs目录下(本例lua默认路径安装,如果安装到其他路径,放入clibs文件夹内即可)。
在这里插入图片描述
操作步3:
打开lua 在这里插入图片描述,输入以下代码进行测试,测试结果为30。

require "mylib" 
a=mylib.Add(10,20)
print(a)

在这里插入图片描述四、在协议库内编写byte解析成位函数并验证,这实验用来说明lua与C如何通过数组进行交互。
操作步骤:
添加以下函数、编译、复制mylib.dll文件到clibs,参考上面Add函数的添加:

//定义把字节解析到位函数
extern "C" int ByteToBools(lua_State* L) 
{
	unsigned int i;
	unsigned char j,m,n;
	int a[16];
    double op1 = luaL_checknumber(L,1); //取出lua调用函数时传递的第一个参数
	lua_settop(L, 0);  //把栈清空
	lua_newtable(L); //新建一个表
	j=(unsigned char)op1;
	//刷新数组值
	for(i=0;i<8;i++)
	{
		m=1;
		m<<=i;
		n=j & m;
		if(n>0)
		{
			a[i]=1;
		}
		else
		{
			a[i]=0;
		}
	}
	//把数组写入到栈
	for(i=0;i<8;i++)
	{
		lua_pushinteger(L,a[i]);        //将数组的数据入栈,此时站内从栈顶开始为a[i]、table
		lua_rawseti(L,-2,i+1);         //将刚刚入栈的数据设置为数组的第i+1个数据,同时这个数据会自动从栈里pop
	}
    return 1;
}

注意这里要改成如下所示:

static luaL_Reg mylibs[] =   
{ 
    {"Add", Add},
	{"ByteToBools", ByteToBools},
    {NULL, NULL} 
};

输入测试代码,执行结果如下:

require "mylib" 
array={}
array=mylib.ByteToBools(255)
for i=1,8 do
print(array[i])
end

在这里插入图片描述五、在协议库内编写lua协议栈打印函数,方便对协议库的调试。
操作步骤1:
添加以下函数:

//打印lua栈内容
static void stackDump(lua_State* L){
    cout<<"当前栈(栈顶到栈底):";
    int i = 0;
    int top = -lua_gettop(L);
    for (i = -1; i >= top; --i) {
        int t = lua_type(L, i);
        switch (t) {
            case LUA_TSTRING:
            {
                printf("'%s' ", lua_tostring(L, i));
            }
                break;
            case LUA_TBOOLEAN:
            {
                printf(lua_toboolean(L, i) ? "true " : "false ");
            }break;
            case LUA_TNUMBER:
            {
                printf("%g ", lua_tonumber(L, i));
            }
                break;
            default:
            {
                printf("%s ", lua_typename(L, t));
            }
                break;
        }
    }
	cout<<endl;
}

函数用法:
比如把Add函数改成这样:

//定义加法函数
extern "C" int Add(lua_State* L) 
{
	cout<<"第一次打印栈内内容"<<endl;
	stackDump(L);
    double op1 = luaL_checknumber(L,1); //取出lua调用Add函数时传递的第一个参数
	cout<<"第二次打印栈内内容"<<endl;
	stackDump(L);
	double op2 = luaL_checknumber(L,2); //取出lua调用Add函数时传递的第二个参数
	cout<<"第三次打印栈内内容"<<endl;
	stackDump(L);
	lua_pushnumber(L,op1+op2); //把结果压入lua栈
	cout<<"第四次打印栈内内容"<<endl;
	stackDump(L);
    return 1;   //返回结果
}

再次编译、复制mylib.dll文件到clibs,输入测试代码,执行结果如下:

require "mylib" 
a=mylib.Add(10,20)
print(a)

在这里插入图片描述
总结:
1、以上步骤操作完成后总体代码如下:

extern "C" {
#include "lua.h"  
#include "lualib.h"  
#include "lauxlib.h"
};
#include <iostream>  
using namespace std;
//打印lua栈内容
static void stackDump(lua_State* L){
    cout<<"当前栈(栈顶到栈底):";
    int i = 0;
    int top = -lua_gettop(L);
    for (i = -1; i >= top; --i) {
        int t = lua_type(L, i);
        switch (t) {
            case LUA_TSTRING:
            {
                printf("'%s' ", lua_tostring(L, i));
            }
                break;
            case LUA_TBOOLEAN:
            {
                printf(lua_toboolean(L, i) ? "true " : "false ");
            }break;
            case LUA_TNUMBER:
            {
                printf("%g ", lua_tonumber(L, i));
            }
                break;
            default:
            {
                printf("%s ", lua_typename(L, t));
            }
                break;
        }
    }
	cout<<endl;
}
//定义加法函数
extern "C" int Add(lua_State* L) 
{
	cout<<"第一次打印栈内内容"<<endl;
	stackDump(L);
    double op1 = luaL_checknumber(L,1); //取出lua调用Add函数时传递的第一个参数
	cout<<"第二次打印栈内内容"<<endl;
	stackDump(L);
	double op2 = luaL_checknumber(L,2); //取出lua调用Add函数时传递的第二个参数
	cout<<"第三次打印栈内内容"<<endl;
	stackDump(L);
	lua_pushnumber(L,op1+op2); //把结果压入lua栈
	cout<<"第四次打印栈内内容"<<endl;
	stackDump(L);
    return 1;   //返回结果
}
//定义把字节解析到位函数
extern "C" int ByteToBools(lua_State* L) 
{
	unsigned int i;
	unsigned char j,m,n;
	int a[16];
    double op1 = luaL_checknumber(L,1); //取出lua调用函数时传递的第一个参数
	lua_settop(L, 0);  //把栈清空
	lua_newtable(L); //新建一个表
	j=(unsigned char)op1;
	//刷新数组值
	for(i=0;i<8;i++)
	{
		m=1;
		m<<=i;
		n=j & m;
		if(n>0)
		{
			a[i]=1;
		}
		else
		{
			a[i]=0;
		}
	}
	//把数组写入到栈
	for(i=0;i<8;i++)
	{
		lua_pushinteger(L,a[i]);        //将数组的数据入栈,此时站内从栈顶开始为a[i]、table
		lua_rawseti(L,-2,i+1);         //将刚刚入栈的数据设置为数组的第i+1个数据,同时这个数据会自动从栈里pop
	}
    return 1;
}
static luaL_Reg mylibs[] =   
{ 
    {"Add", Add},
	{"ByteToBools", ByteToBools},
    {NULL, NULL} 
};
extern "C" __declspec(dllexport)
int luaopen_mylib(lua_State* L)    //注意“luaopen_mylib”函数名内的“mylib”,要与输出的文件名一致
{
    const char* libName = "mylib";//注意"mylib",要与输出的文件名一致
    luaL_register(L,libName,mylibs);
    return 1;
}

2、本文详细讲解了,使用VS2010如何新建一个DLL工程,如何移植LUA协议库,协议库如何与lua进行数组交互、变量交互。
3、下节将讲解在当前基础上如何移植Snap7协议库到工程内,如何让Snap7与Lua协议库相互兼容,能顺利的编译完成,欢迎大家持续关注。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值