调用动态链接库 4 – 结构型参数的设置

    C 语言中的结构(struct),在一些简单情况下,可以和 LabVIEW 中的 Cluster 相对应。但是,对于比较复杂的情况,LabVIEW 中的 Cluster 要做适当调整,才能够对应起来。

    在讨论结构型参数的映射前,一定要先了解一下字节对齐的概念。我在这里只做一个简单说明,详细内容可以查找相关的专题文章。
    C 语言中的一个结构 typedef struct { char a; int b} MyStct;  结构中的元素a所在的地址是:0xAAAA0000,b 的存放地址是与结构的字节对齐设置相关的。如果采用1字节对齐,b是紧挨着a存放的,b的地址就是:0xAAAA0001;如果采用2字节对齐,b的存放地址是紧挨着a的第一个偶数地址,也就是:0xAAAA0002;如果采用4字节对齐,b的存放地址是紧挨着a的第一个4整数倍地址,也就是:0xAAAA0004……
    C 语言的字节对齐数可以由 #pragma pack 指令指定,也可以在工程属性里指定。但是 LabVIEW 的 Cluster 只能是1字节对齐的。因此,C 语言中,非1字节对齐的结构与Cluster对应时,一定要做适当调整。比如,结构 typedef struct { char a; int b} MyStct;  是2字节对齐的,那么,对应的LabVIEW Cluster 第一个元素还应该是 I8 型的a,但是,不能紧接着就放b,因为C语言中,b的起始地址不是紧挨着a的,他们中间还有一个无意义的数据,C的结构体虽然表现不出来,LabVIEW中却需要把它考虑进去。
    如果是自己编写一个DLL给LabVIEW使用,为了方便,可以把C代码中所有的结构都设为1字节对齐。

    C 语言的结构中如果还嵌套了数组,是不能直接对应于LabVIEW中嵌套了数组的Cluster的。在LabVIEW中,只能把数组的元素都拆开来放在Cluster中。

    下面是一些对应的实例:

C LabVIEW

#pragma pack (1)
typedef struct { char a; int b} MyStct;
MyStct* testStruct;

#pragma pack (2)
typedef struct { char a; int b} MyStct;
MyStct* testStruct;

#pragma pack (4)
typedef struct { char a; int b} MyStct;
MyStct* testStruct;

#pragma pack (1)
typedef struct { char a; char* str; int b} MyStct;
MyStct* testStruct;

#pragma pack (1)
typedef struct { char a; char str[5]; int b} MyStct;
MyStct* testStruct;

    上面这个表中有两点需要注意的:
    一是,表格中的第四个例子,结构中含有一个指针,LabVIEW中的Cluster只能用一个U32数值(32位系统上,64位系统上使用U64)来表示指针的地址。不能把指针指向的内容放到Cluser中去。后面的章节再讨论当我们在LabVIEW中得到了一个数据的地址后,如何从这个地址中把数据拿出来。
    第二,上面C语言中声明的 testStruct 变量,是指向结构的指针。就是说C函数的变量类型为结构的指针时,才能在LabVIEW中使用Cluster与之对应。CLN节点的配置面板中,没有一个专门的参数类型叫做“struct”或者“Cluster”,选择“Adapt to Type”就可以了。
    如果参数的类型就是结构而非指针,考虑到C函数参数的压栈顺序,把一个结构体作为参数传给函数,等价于把结构中每个元素分别作为参数传递给函数。下面是一个例子:

输入/输出

输入

输出或兼作输入输出

C语言声明

typedef struct{int left; int top;} Position;
long TestStructure(Position inPos);

typedef struct{int left; int top;} Position;
long TestStructure(Position *pos);

LabVIEW
中的配置

 

 

LabVIEW
的使用

 

 

 《我和 LabVIEW》目录

Advertisements

9 thoughts on “调用动态链接库 4 – 结构型参数的设置

  1. 阮老师,你好!我用LABVIEW作了一个DLL,用labview程序可以调用,但是我用VC++调用,我把DLL文件复制在WINDOWS->SYSTEM下了,在编译时就会报错!请指教!谢谢!

  2. Delphi的函数参数压栈方式与C不同。你需要查找一些相关资料,也许改变一下参数顺序就好了,但我也不确定,没用过Delphi.

  3. 你好,我用Labview调用Delphi编写的一个dll时,有个函数的参数是指向一个结构的指针,我按照你上文中所说的使用一个Cluster来对应,结果运行出现一个严重内部错误:ThEvent.cpp中209行出现错误,请问你遇到过这样的问题吗?能不能给我提供一些解决问题的思路?多谢。

  4. 你的这个想法恐怕实现不了。你自己开发的DLL若需要改变LabVIEW控件中的数据,实现起来相当麻烦,需要调用LabVIEW中一些特殊的函数,而我也不是太确定这些函数是否是公开给外部用户的。比较容易的实现方法是,在LabVIEW中编写一个多线程程序。就是说用动态调用的方式开一个新的线程,这个线程专用于更新控件上的数据。它时刻监视DLL返回的数据,一旦数据有所变化,就去更新控件上的数据。

  5. 你好~我有个labview的难道解决了很久没成功.想请教你一下.比如我用labview来做界面,用dll来处理信息.在labview上有些控件我想让dll自主的去更新,而不是由labview的数据流程去更新.比如有一个文本显示控件.我有什么办法可以在初始化时把这个控件告诉dll.然后在以后的某个时刻dll自己去更新了文本显示控件的内容.些时不由labview的执行流程决定…谢谢..有什么好的解决方法麻烦告诉我一下..也可以随便发个邮件给我..email:xtliaohanxin@163.com

  6. 我现在想调用dll库中的函数,函数设置是long LEDAPI AddText(char *str, LPRECT rect, long method, long speed, long transparent, char *fontname, long fontsize, long fontcolor); 现在想知道str  rect在labview中的数据类型是?查了好久,还是不明白怎么设置,谢谢大侠啦

  7. 这个工具小牛牛还在NI 10周年庆的时候说道了。确实啊,蛮多人的心血在里面的。最最开始的时候丁立超整天在唠叨,说CLN太难用了,很多客户打电话给他,他都累死了,到现在做的比较完善了。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s