开发日记3.11

此篇用于记录发那科数控机床(Fanuc CNC)采集程序开发中,C语言写底层然后用aardio写窗口调用dll的摸索出来的类型对应和踩坑整理。
由于发那科提供的开发套件是C语言的,所以由C语言编写动态库供其他程序调用,窗口界面也可以使用python等其他程序,C代码可移植Linux平台,本篇为Win平台。
后续再录个视频做一些说明。
后续更新移植Linux方法和发那科机床二次开发记录记录整理。

安装mingw32

下载安装配置

官方地址下载安装:https://sourceforge.net/projects/mingw/
安装方法:https://blog.csdn.net/HandsomeHong/article/details/120803368
↑记得最后要添加一下环境变量
mingw64 编译32位失败,待继续研究。https://zhuanlan.zhihu.com/p/413181676#
如果官网下载太慢可以用我提供的备份:https://gitee.com/dvaloveu/lovedva/blob/master/blog_attachments/mingw-get-setup.exe
下载链接失效请私信或者文章最下方评论,QQ465318701 答案:没有 xixixi_0987@hotmail.com
安装完成后用以下命令测试是否安装成功
gcc --version
g++ --version

用aardio测试范例程序

打开范例-调用其他语言-GCC-C++
用这个范例测试,注意去除 -municode 这个编译选项,即可成功。
-municode 这个选项与 Unicode(UTF-16) 宽字符相关,是VC++编译器的选项,若使用mingw就没有这个选项,处理宽字符用别的宽字符类型。
↑个人建议C语言编写dll库时不使用宽字符,在外部调用的时候封装返回结果再使用中文枚举类封装展示。

aardio中调用dll

1
2
var dll = raw.loadDll($"\cpp.dll",,"cdecl"); //必须要放在aar工程目录下
console.log("dll调用结果:",dll.hello())

C语言函数封装和编译

函数声明

编写可以被DLL导出,被其他程序调用的函数,使用宏来控制是否导出为可被外部调用的方法

1
2
3
4
5
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif

函数声明写法

1
2
DLL_EXPORT int hello();
DLL_EXPORT int connectCNC(char *str, unsigned short port, long timeout, unsigned short *FlibHndl );

编译运行和编译DLL库

1
gcc main.c -o myprogram -L. -lfwlib32; .\myprogram.exe 
1
gcc main.c -o cpp.dll -DBUILD_DLL -L. -lfwlib32  -shared -s  -m32 -O2 -static -lgcc -lstdc++ ;mv cpp.dll .\aardio窗体\ -force

数据类型和结构体传参示例

根据手册里的API数据类型,按照对应的结构体传参,参考范例-调用其他语言-C语言-生成DLL,在线手册网站:https://bbs.aardio.com/doc/reference/

传字符串指针char *str和short整型指针

C函数

1
2
3
int connectCNC(char *str, unsigned short port,  long timeout, unsigned short *FlibHndl ){
return cnc_allclibhndl3( str, port, timeout, FlibHndl);
}

aardio 对应写法

1
2
3
4
5
6
7
8
//声明 指针用结构体/表
var pthndl = {
WORD x=666;
}
//传入结构体指针,接收返回值,和结构体数据
var ret,pthndl = dll.connectCNC("192.168.1.1",tonumber(mainForm.edit3.text),10,pthndl)
console.log("返回值:",ret)
console.log("连接cnc获取句柄:",pthndl.x)

传结构体参数

C函数和结构体定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int getCNCStatus(unsigned short FlibHndl, ODBST * odbst){
return cnc_statinfo( FlibHndl, odbst ) ;
}

typedef struct odbst {
short hdck ; /* handl retrace status */
short tmmode ; /* T/M mode */
short aut ; /* selected automatic mode */
short run ; /* running status */
short motion ; /* axis, dwell status */
short mstb ; /* m, s, t, b status */
short emergency ; /* emergency stop status */
short alarm ; /* alarm status */
short edit ; /* editting status */
} ODBST ;

对应aardio表定义和传参写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//设备状态结构体定义
ptODBST = {
word hdck ; /* handl retrace status */
word tmmode ; /* T/M mode */
word aut ; /* selected automatic mode */
word run ; /* running status */
word motion ; /* axis, dwell status */
word mstb ; /* m, s, t, b status */
word emergency ; /* emergency stop status */
word alarm ; /* alarm status */
word edit ; /* editting status */
}

ptODBST=cStruct.ptODBST
var ret,ptODBST=dll.getCNCStatus(pthndl.x,ptODBST)
mainForm.static16.text=enumPack.ODBSTrun[ptODBST.run];
console.log("getCNCStatus:",ret)

字符串数组 char[]传参

C函数和结构体定义

1
2
3
4
5
6
7
8
9
int getExePrgname( unsigned short h, ODBEXEPRG * odbexeprg){
return cnc_exeprgname(h, odbexeprg); //获取文件名
}

typedef struct odbexeprg {
char name[36]; /* running program name */
long o_num; /* running program number */
} ODBEXEPRG; /* */

对应aardio表定义和传参写法

1
2
3
4
5
6
7
8
9
var ptODBEXEPRG= {
byte name[36] ; /* running program name */
long64 o_num; /* running program number */
}

var ret,ptODBEXEPRG=dll.getExePrgname(pthndl.x,ptODBEXEPRG)
console.log("getExePrgname:",ret)
mainForm.static17.text=ptODBEXEPRG.name;

结构体嵌套和结构体数组传参

C函数和结构体定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct iodbpsd {
short datano ; /* data number */
short type ; /* axis number */
union {
char cdata ; /* parameter / setting data */
short idata ;
long ldata ;
REALPRM rdata ;
char cdatas[MAX_AXIS] ;
short idatas[MAX_AXIS] ;
long ldatas[MAX_AXIS] ;
REALPRM rdatas[MAX_AXIS] ;
} u ;
} IODBPSD ;

对应aardio表定义和传参写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//读取公共参数结构体
MAX_AXIS=9;

ptiodbpsd ={
word datano ; /* data number */
word typePra ; /* axis number */
union u= {
byte cdata ; /* parameter / setting data */
word idata ;
int ldata ;
rdata={
int prm_val;
int dec_val ;}
byte cdatas[]={length = MAX_AXIS;} ;
word idatas[]={length = MAX_AXIS;} ;
int ldatas[]={length = MAX_AXIS;} ;
struct rdatas[] ={length = MAX_AXIS;
{int prm_val;
int dec_val ;}};
} ;
} ;


cStruct.MAX_AXIS=3
ptiodbpsd=cStruct.ptiodbpsd
var ret,ptiodbpsd=dll.getParam(pthndl.x,6712,0, (4+4*3), ptiodbpsd )
mainForm.static18.text=ptiodbpsd.u.ldata;