我现在用labview调用Vc++编写的CAN-PCI通信卡的DLL,其中有一个函数send message(unsigned char nDevice,unsigned char Port,Hs_MSG *pMsg, int nLenght).pMsg:发送缓冲区首址;Hs_MSG是结构体,如下:

typedef struct
{
unsigned char Port;
unsigned long Id;
unsigned char Ctrl;
unsigned char pData[8];
}HSCAN_MSG;


        我把该函数自动封装成VI,调用该VI、给Msg参数创建输入控件。结果为:该输入控件为一个簇变量,该簇变量中除包含Hs_MSG结构体中的四个参数外,在Port的后面还有三个“标签”为@dummycontrol@的数值变量。请问三个“@dummycontrol@数值变量”指的是什么?

      调试的时候发现 没有@dummycontrol@时,不能实现正常的通信;添加@dummycontrol@、随便设定值后、可实现正常的通信。


这是一个非常有意义的问题,这里涉及到数据结构中所谓对齐的概念。

LV中的簇各个元素之间在内存中存储是无间隙的,也就是说簇的大小等于簇中所有元素大小之和。而C语言的结构是不同的,结构的大小不一定等于其各个元素大小之和,需要用sizeof函数确定。

C语言的结构为了保证运算的高效性,一般采用字对齐方式,在16位微机中,一个字等于两个字节,在32位微机中,一个字等于4个字节。

我通过CVI创建了与您同样的结构体和DLL,如下所示:
   typedef struct
{
 unsigned char Port;
 unsigned long Id;
 unsigned char Ctrl;
 unsigned char pData[8];
}HSCAN_MSG;
  
  
extern long int DLLEXPORT GetMsg(HSCAN_MSG *msg) ;


#include
#include      /* needed if linking DLL in external compiler; harmless otherwise */
#include
 #include    
#include "dll.h"


BOOL __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
     /* The DllMain function is called when ever the DLL is loaded and    */
     /* unloaded. Place Initialization code for the DLL in this function. */
    if (fdwReason == DLL_PROCESS_ATTACH) {
        /* Place any initialization which needs to be done when the DLL */
        /* is loaded here. */
        if (InitCVIRTE (hinstDLL, 0, 0) == 0)       /* needed if linking DLL in external compiler; harmless otherwise */
            return 0;   /* out of memory */
     
    } else if (fdwReason == DLL_PROCESS_DETACH) {
        /* Place any clean-up which needs to be done when the DLL */
        /* is unloaded here. */
        CloseCVIRTE ();     /* needed if linking DLL in external compiler; harmless otherwise */
    }
    /* return FALSE to abort if initialization fails */
    return 1;
}

BOOL __stdcall DllEntryPoint (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    return DllMain(hinstDLL, fdwReason, lpvReserved);
}

   long int DLLEXPORT  GetMsg(HSCAN_MSG *msg)
{
    int i;
   
    msg->Port=5;
    msg->Id=10;
    msg->Ctrl=2;
   
    for(i=0;i<8;i++) msg->pData[i]=i;
   
    return msg->Port;
   
   
   
}


在上述结构中,通过导入共享库,自动产生下列簇结构:
Picture
如上所述,因为默认为四字节对齐方式, ID为整形数占用四个字节,即一个字,因此Port之后必须插入3个无用字节,合成一个字的空间。

如果是我们自己创建的DLL,供LV调用,在头文件中加入:
#progma (1),就可以保证C的结构为字节对齐的,此时,LV中调用就不需要占位符了。

记得我在其它文章中详细介绍过对齐的概念,这里就不重复了。
Picture
 





Leave a Reply.