关键技术4:从CVI中导出dll供外部使用

本文介绍如何将LabWindows/CVI开发环境中的代码转换为动态链接库,并将其嵌入到Visual C++项目中,实现两种开发环境的协同工作,特别适用于半实物仿真系统的构建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
NI的LabWindows/CVI 开发环境已经升级到2009版,不仅可以使用Windows下 Borland C++、Visual C++编译的dll,而且可以直接用这些外部编译器替代CVI本身的编译器来编译原来的代码资源!相比原来LabWindows/CVI 5.5 ,2009版在多编译器环境下协同开发的阻力大大减少,提供了诸多便利,由此组合出多编译环境的协同开发方法至少由9种。这里,考虑的是:将现有的CVI工程代码转换为dll,嵌入到Visual C++工程中去。用意很显然——用于半实物仿真系统构造。
 
实现这一技术主要分为两阶段:
1、在CVI中重新配置现有CVI工程代码,生成Visual C++可用的动态链接库;
2、在新的Visual C++做必要修改,调用CVI的动态链接库。
 
详细步骤如下:
一、CV部分,主要是代码上的修改和配置上的修改。
 
    代码上,找出原有CVI工程的程序入口文件,一般是main所在C文件,修改之或者新建C文件包含之,相当于制造一个dll外壳。这个外壳至少要包含以下代码:
 

#include <cvirte.h>

int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
 switch (fdwReason)
 {
  case DLL_PROCESS_ATTACH:
   if (InitCVIRTE (hinstDLL, 0, 0) == 0)
    return 0;   /* out of memory */
   break;
  case DLL_PROCESS_DETACH:
   CloseCVIRTE ();
   break;
 }
 
 return 1;
}

int __stdcall DllEntryPoint (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
 /* Included for compatibility with Borland */

 return DllMain (hinstDLL, fdwReason, lpvReserved);
}


这段代码基本上是操作系统的要求,不涉及CVI运行时系统。要生成可供外部实用的dll,代码方面还有一个细微的修改:修改面板的加载方式。一般的main函数加载面板的方式如下:
 if ((panelHandle = LoadPanel (0, "testCVI.uir", PANEL) ) < 0)
  return;
 DisplayPanel (panelHandle);
 RunUserInterface ();
 DiscardPanel (panelHandle);
 ...
 
为了能够使面板能够使用dll中callback函数,必须使用LoadPanelEx加载之:
 if ((panelHandle = LoadPanelEx (0, "testCVI.uir", PANEL, __CVIUserHInst ) ) < 0)
  return;
 DisplayPanel (panelHandle);
 RunUserInterface ();
 DiscardPanel (panelHandle);
 ...
 
 其中的 __CVIUserHInst 是默认的dll加载句柄。
不仅是main函数,整个工程代码中的LoadPanel都必须如上修改。
 
CVI编译配置还需要做一些修改。
1、Build -> Target Type 设置为Dynamic Link Library
2、Option-> Build Option,检查其中的函数调用方式,确保与Visual C++ 保持一致。一般WINAPI使用的是__stdcall方式,这里选择__stdcall。
3、Build -> Target Settings 设置导出函数的方式为使用专门为dll编写的"Include file"的符号:
 不使用与UIR面板同名的testCVI.h是为了避免修改testCVI.UIR后自动覆盖了它。采用单独的.h来指定dll的导出函数更加安全。testCVIDLL.h中是关于dll的导出信息,用于外部编译器在编译期使用。由于Visual C++默认是C++编译模式,而CVI向来是标准C编译模式,因此,这个头文件必须使用C宏保护:
 

/*if using C++ Compiler to compile the file, adopting C linkage mode
 */
#ifdef __cplusplus
extern "C" {
#endif

 

 /*  your  function declaration  for dll   */

 

#ifdef __cplusplus
}
#endif

 
 
4、嵌入UIR面板。旧版的LabWindows/CVI不支持嵌入面板,因此在使用CVI生成的dll同时,也需要将uir面板拷贝到相同的运行时路径(./Debug/)下。2009版的LabWindows/CVI则可以直接配置为嵌入UIR文件:

通过在该配置页面设置Custom Copy directory,甚至连拷贝dll到Visual C++工程下的运行时目录这一步也省了。
 
5、Ctrl+M 生成 dll、lib的debug版或者release版。
 
二、Visual C++部分
 
    主要是编译设置和链接设置。
 
1、设置函数调用方式与CVI保持一致:
 
2、将dll的编译头lib添加进来:
 
需要说明的是,添加lib文件有多种方式:(1)直接add file;(2)添加目录到库搜索路径,然后给出库的文件名;(3)直接添加库的路径名。头文件的添加也是类似的,这里是将dll的头文件直接复制到了工程根目录下,因此无须多劳。另外,在Visual C++的编译器选项中,/Gz指定__stdcall调用方式, /Gd 指定__cdecl调用方式。 

这个例子最后是实现在MFC程序中调用CVI面板程序:
 

 

 

 

常见问题:

1、链接错误2001:找不到dll中符号。这是由于Visual C++默认对*.cpp文件中的函数调用(包括dl中的导出函数)采用C++命名方式造成的,需要使用 extern "C"宏进行保护。   思路来自这里 关于dll调用原理的解释和dll头文件格式的分析

 

相关资源:
1、 本文实例NI的官方例子 为基础,修正若干错误。下载分别在 、和

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值