文章目录
- 1.前言
- 2.前期准备
- 3.创建CodeSys库工程
- 3.1.函数名必须包含_cext
- 3.2.生成m4、c文件
- 4.搭建编译环境,编译出动态库*.so
- 4.1.将ExtensionSDK文件夹拷贝到板子的一个目录中。
- 4.2.创建工程目录,且将前面生成的m4、c文件拷贝到这个工程目录下
- 4.3.执行make
- 4.4.实现函数
- 4.5.执行编译
- 5.将*.so文件导入到库工程中
- 6. 将库工程另存为编译库
- 7.安装并使用编译好的库
- 8.结语
1.前言
假如我们需要在CodeSys的编程环境中使用我们自己的功能,比如:用第三方的IO板卡通讯、PDF文件生成、相机采集图像并处理等等一些复杂的功能,那就可以使用CodeSys提供的【Extension SDK】功能,通过C语言动态库接口来实现。
这里简单记录一下如何创建能够被CodeSys识别的C语言动态库。
2.前期准备
这里我运行codesys runtime的环境是一个arm64板子,板子上已经安装好了gcc等编译工具链。(一开始我是打算直接在本地的win x64上搞得,但是官方提供的例子是在linux上操作的,那我只好用arm开发板了)
通过CodeSys开发环境安装的runtime
3.创建CodeSys库工程
参考这里【CodeSys V3.5创建一个编译库】,创建一个Library工程。
需要注意的是,一定要按照上面例程的流程:先创建标准工程–》工程另存为*.Library文件。只有这样才不会在将工程另存为编译库时报错(会报文档生成库未安装之类的错误),具体我也不知道为啥。
假如直接创建Library工程,然后在工程另存为编译库时报错,就需要安装CODESYS Library Documentation Support:
在程序组织单元页面中添加POU(函数),注意我们目前是只能通过C的库调用函数,暂时还不能实例化C++的类,但是C的库里面可以包含C++的内容,只要导出到库的函数是C的形式就行,这个可以等下看看我的C文件就知道什么意思了。
3.1.函数名必须包含_cext
创建函数的时候,函数名必须要包含_cext,否则在后面编译时会报错。
创建好函数并且定义好输入变量、返回值后,在函数节点上右键-》属性-》编译中勾选外部实现。
3.2.生成m4、c文件
创建好函数后,就可以根据函数导出m4、c文件了。
点击编译-》生成运行时系统文件
然后选择好文件夹、勾选M4、C,然后点击确定,就可以得到m4、c文件了。
4.搭建编译环境,编译出动态库*.so
根据【Extension SDK】的指导,
4.1.将ExtensionSDK文件夹拷贝到板子的一个目录中。
我的这个文件夹是在【C:\Program Files\CODESYS 3.5.19.60\CODESYS\CODESYS Control SL Extension Package\4.10.0.0】里面,具体要看你的CodeSys的安装目录在哪里。
然后我将其拷贝到板子的一个目录下:
4.2.创建工程目录,且将前面生成的m4、c文件拷贝到这个工程目录下
我在板子的目录下创建的myPrj文件夹,然后将m4、c文件拷贝到了里面,如下图所示:
4.3.执行make
cd 到myPrj目录,然后执行
make -f ../ExtensionSDK/makefile newproject
然后就会在此文件夹中生成make文件
4.4.实现函数
打开c文件,对函数进行实现。
4.5.执行编译
在对C文件进行实现后,便可以进行编译了。
make all
此时会报错
因为它默认使用的编译器是gcc,是c语言的编译器,而我们在C文件中用到了C++的东西string,所以就报错了。
因此我们还需要改一下make文件,将CC = gcc改成 CC = g++。假如你对make语法熟悉,也可以改一下其他的。
再编译就没问题了。
于是,便在out文件夹中得到了*.so文件。
5.将*.so文件导入到库工程中
将在板子上编译得到的so文件,拷贝到我们的windows电脑上,然后在工程中导入。
点击C实现库-》添加-》选择so文件。
但是此时一般会报错:
库命名空间可以在这里看:
工程信息-》标题
比如我这里是ZY1,那么,so文件就要改成以这个进行结尾:
好,没问题了,记得要选择正确的设备。
这样,函数的实现就有了。
6. 将库工程另存为编译库
然后就得到了我们适用于ARM64的库了
7.安装并使用编译好的库
我们新建一个标准工程、并且安装、调用刚才的库
执行并查看一下函数有没按照预期运行:
我们的C函数实现的是:a、将传递进来的字符串加上"Hello World and ZY"后保存到返回值b中;b、对返回值a赋值17909;c、对返回值c赋值1.23456.
#include "CmpStd.h"
#include "CmpErrors.h"
#include "CmpItf.h"
#include "FileTransferDep.h"
#include <string>
void CDECL CDECL_EXT myfunction_cext(myfunction_cext_struct *p)
{
std::string aStr = p->a;
aStr += "Hello World and ZY";
p->MyFunction_cext.a = 17909;
memcpy(p->MyFunction_cext.b, aStr.c_str(), aStr.length() + 1);
p->MyFunction_cext.c = 1.23456;
}
可以看到,与预期效果一致。
而且在我们的板子上,可以看到刚才包含进来的库文件已经被上传到板子的特定文件夹中了:
8.结语
有了这个接口,只要我们对OpenCV、相机驱动库等进行封装,然后提供对应的操作函数给接口,就可以实现PLC的视觉检测功能。完美。
参考:
【CodeSys V3.5创建一个编译库】
【Extension SDK】