ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

LabVIEW生成DLL全攻略:跨语言调用、接口设计与工程实践

LabVIEW生成DLL全攻略:跨语言调用、接口设计与工程实践 简介本资源是一套面向LabVIEW开发者与嵌入式/跨平台集成工程师的DLL生成实战教程聚焦于将LabVIEW代码封装为标准Windows动态链接库DLL解决LabVIEW与C/C、Python、MATLAB等外部环境协同调用的核心痛点适用于工业自动化、测试系统集成及混合编程开发场景。压缩包共18个文件涵盖6个核心VI含SpeedAnalysis、ErrorAnalysis等算法模块、2个.lvproj工程文件、2个.lvlps库文件、1个.h头文件、1个.lib导入库、1个.dll可执行体、1个.ini配置文件及1份详尽的Word教程文档完整呈现从VI设计、接口定义、编译配置到导出验证的全流程。资源体积仅492KB结构紧凑、即下即用。目前已有267人学习下载提供可直接运行的范例工程、标准化别名aliases配置、VISA通信与数据分析典型VI模板以及共享库命名规范与调用注意事项说明显著降低LabVIEW生成DLL的学习门槛与集成风险。1. 项目概述为什么LabVIEW开发者需要掌握DLL生成如果你在用LabVIEW做项目尤其是涉及到和C/C、C#、Python甚至其他硬件厂商提供的库进行交互时迟早会碰到“DLL”这个词。很多刚接触LabVIEW的工程师会觉得LabVIEW不是图形化编程吗为啥要折腾DLL我刚开始也这么想直到有一次客户给了一个用C写的核心算法模块要求集成到我们的测控系统里。对方只提供了一个.dll文件和一堆看不懂的头文件那一刻我才意识到不会玩转DLL在工业自动化、测试测量这个圈子里很多高级项目根本玩不转。简单来说DLL动态链接库就像是一个功能的“工具箱”。LabVIEW本身很强大但总有它不擅长或者没有现成模块的领域。比如某些复杂的数学运算、特定的硬件驱动、或者为了代码安全和复用而用C语言写的核心算法。把这些功能打包成DLLLabVIEW就能像调用自己的子VI一样去调用它们极大地扩展了LabVIEW的能力边界。生成DLL则是这个过程的逆过程把你用LabVIEW精心编写的、稳定可靠的逻辑比如一个复杂的信号处理算法、一个专用的通信协议栈封装起来提供给其他开发环境如C#上位机、Python数据分析脚本使用。这不仅仅是技术需求在多人协作、跨团队交付、软件架构分层时更是非常实用的工程实践。所以这个教程要解决的就是如何把LabVIEW的图形化代码“编译”成标准的Windows动态链接库。这不仅仅是点击几下鼠标里面涉及到接口设计、数据类型映射、内存管理、错误处理等一系列坑。接下来我会结合我踩过的无数个坑从为什么做、怎么做、到怎么做得稳给你拆解清楚。2. 核心思路与方案选型理解LabVIEW DLL的本质在动手之前我们必须搞清楚LabVIEW生成的DLL和传统C编译器生成的DLL有什么异同。如果你以为只是换了个编译器那就大错特错了这里面的门道直接决定了后续使用的顺畅程度。2.1 LabVIEW生成DLL的两种核心模式LabVIEW主要通过“调用库函数节点”的镜像——即“生成DLL”的功能来输出库文件。其核心思路是为你编写的LabVIEW代码通常是一个VI创建一个标准的C语言接口。这里主要有两种工作模式普通DLL模式这是最常用、也最推荐给新手的模式。LabVIEW会生成一个.dll文件和一个对应的.h头文件。头文件里声明了C风格的函数原型。任何支持调用标准C DLL的开发环境如C/C、C#、Python的ctypes、LabVIEW自己都可以通过这个头文件了解函数名、参数和返回值从而调用你的LabVIEW代码。这种模式下DLL的内部仍然由LabVIEW运行时引擎驱动因此目标机器上必须安装相应版本的LabVIEW运行时引擎。独立DLL模式在LabVIEW的专业版或更高版本中你可以创建“独立应用程序”并选择将某些VI编译为“共享库”。这种方式生成的DLL其目的是为了在多个LabVIEW独立应用之间共享代码减少磁盘空间占用。它通常与LabVIEW的应用程序生成器紧密相关接口可能更依赖于LabVIEW内部机制通用性反而不如第一种模式。对于需要提供给非LabVIEW环境使用的场景我们几乎总是选择第一种模式。2.2 关键工具lv_shared_lib模板与项目结构当你新建一个项目并打算生成DLL时LabVIEW会引导你使用“共享库”项目模板。这个模板会自动创建一个规范的项目结构包含源代码你的主要功能VI。库名.c和库名.h文件这是LabVIEW自动生成的C语言接口文件是外部程序调用你的DLL的桥梁。千万不要手动修改这些文件除非你知道确切后果因为每次重新生成DLL时它们都会被覆盖。构建规范在项目浏览器中右键点击“程序生成规范”-“新建”-“共享库(DLL)”。这里包含了生成DLL的所有设置是我们要重点配置的地方。2.3 方案选型背后的考量为什么选择生成标准C接口的DLL而不是其他方式如ActiveX、.NET Assembly通用性最强C接口是跨平台、跨语言的“世界语”。从古老的Visual Basic 6到现代的Go语言几乎都能以某种形式调用C DLL。性能开销相对明确相比于通过ActiveX或.NET的互操作层直接调用C DLL的性能开销通常更小尤其是在高频数据交换时。依赖明确依赖项就是LabVIEW运行时引擎部署时相对清晰。而.NET Assembly可能会引入复杂的.NET框架版本问题。注意生成DLL并不意味着你的代码脱离了LabVIEW。恰恰相反这个DLL是LabVIEW运行时引擎的一个“插件”。因此目标系统上必须安装对应版本或更高版本的LabVIEW运行时引擎否则DLL将无法加载。这是新手最容易忽略、也最容易导致“初始化例程失败”错误的关键点。3. 详细配置与实操步骤解析理解了原理我们进入实战环节。我将以一个具体的例子贯穿始终假设我们有一个LabVIEW VI它接收一个双精度浮点数数组和数组大小计算数组的平均值和标准差然后返回这两个值。3.1 第一步准备源VI功能实现首先你需要在LabVIEW中编写并调试好你的核心功能VI。为了能成功生成DLL这个VI必须满足以下条件设置连接器窗格这是定义DLL函数接口的基础。右键点击VI前面板的右上角图标选择“显示连接器”。通常为简单的输入输出分配一个4x2x2x2的窗格就够用。将需要作为输入参数的控件如我们的数组输入、数组大小连接到连接器窗格左侧的端子将需要作为输出参数的控件如平均值、标准差连接到右侧的端子。严格定义输入/输出控件的数据类型这是避免后续调用时内存访问错误的重中之重。例如数组输入应明确是一维双精度数组数组大小应为32位整数。避免使用变体、复杂簇等不易映射到C语言的数据类型作为顶层参数。如果必须使用需要精心设计。完善的错误处理在VI内部包含完整的错误处理链。DLL的调用方需要知道操作是否成功。通常的做法是在连接器窗格上添加一个“错误输入”和一个“错误输出”簇参数这样可以将错误信息传递出去。3.2 第二步创建共享库构建规范在项目浏览器中右键点击“程序生成规范”选择“新建”-“共享库(DLL)...”。会弹出共享库属性配置对话框这是整个流程的核心。3.3 第三步深度配置构建规范避坑关键配置对话框有多个标签页我们逐一拆解关键设置“信息”页面目标文件名给你的DLL起个名字例如MyStatistics.dll。目标目录选择DLL文件的输出路径。“源文件”页面将你准备好的主VI从“项目文件”列表添加到“始终包括”的“项目项”中。这就是你要导出的功能。“图标”页面可以忽略不影响功能。“目标”页面重要目标文件名和目标目录通常与“信息”页面同步无需重复设置。支持目录如果你VI中调用了其他非标准安装路径的VI或库需要在这里添加它们的路径确保打包时能找到。“源文件设置”页面核心配置选中你添加的VI右侧会出现该VI的导出配置。导出目录通常保持默认。函数名这是外部程序调用时使用的函数名。默认可能是VI名但建议改成更符合C语言习惯的名字如CalculateMeanStdDev。避免使用空格和特殊字符。调用规范选择stdcall (WINAPI)。这是Windows平台上DLL函数最常用的调用约定能确保参数被正确地从堆栈中清理。如果将来需要跨平台到Linux则需要选择C调用约定。线程安全如果你的VI是可重入的即多个线程同时调用同一个VI实例不会出错可以选择“在任意线程中运行”。这能提高调用方的并发性能。如果不确定选择“在UI线程中运行”最安全但性能有损。我个人的经验是对于计算密集型的VI设计为可重入并选择“在任意线程中运行”能获得更好的性能对于涉及硬件IO操作的VI选择“在UI线程中运行”更稳妥。“参数配置”页面数据类型映射的关键这是最容易出错的地方。你需要在这里定义每个参数的C语言数据类型。选中你的VI下方会列出其连接器窗格上的所有参数。为每个参数配置“类型”和“传递方式”。数值类型如DBL, I32“类型”通常选择对应的C类型如double,int32_t。“传递方式”选择“值”。数组这是难点。对于输入数组“类型”选择“数组”“数据类型”选择对应的元素类型如double。“传递方式”必须选择“数组数据指针”。LabVIEW会要求你指定一个“数组大小参数”这就是为什么我们单独传了一个“数组大小”参数的原因。你需要将“数组大小”参数与这个数组参数关联起来。对于输出数组配置类似但“传递方式”通常也选择“数组数据指针”并由调用方预先分配好内存这需要额外约定或者通过返回一个LabVIEW管理的数组句柄更复杂。在我们的例子中平均值和标准差是简单的标量输出用“值”传递即可。字符串“类型”选择“字符串”“传递方式”选择“C字符串指针”。注意内存管理通常由调用方分配缓冲区DLL填充。错误簇LabVIEW为错误簇提供了预定义的类型“LabVIEW错误簇”直接选用即可。“传递方式”选择“值”或“指针”均可但为了保持一致性我通常选择“指针”即“错误簇指针”。“高级”页面启用调试在开发阶段勾选会生成调试信息方便排查问题。发布时应取消勾选以减小文件体积。删除未使用的成员建议勾选可以优化生成的代码。“依赖项”页面这里会列出你的DLL所依赖的所有LabVIEW VI库、模块等。确保它们都被正确包含。通常保持默认即可。3.4 第四步生成与验证配置完成后点击“生成”按钮。LabVIEW会进行编译并在输出目录生成MyStatistics.dll动态链接库文件。MyStatistics.hC语言头文件。MyStatistics.cC语言源文件通常不需要关心。可能还有MyStatistics.lib用于静态链接。验证生成是否成功最直接的方法是用LabVIEW自己来调用。新建一个VI放置一个“调用库函数节点”在配置对话框中库名/路径选择你刚生成的DLL函数名选择CalculateMeanStdDev然后按照头文件中的定义逐个参数配置好类型和传递方式。连接好输入控件和输出指示器运行。如果能够正确计算并返回结果说明DLL生成基本成功。4. 核心环节C语言接口与数据类型映射详解仅仅生成DLL还不够要让别人或其他语言能用必须理解生成的C接口。打开MyStatistics.h文件你会看到类似下面的代码#ifndef __MyStatistics__ #define __MyStatistics__ #include extcode.h #ifdef __cplusplus extern C { #endif /* 错误簇结构体定义LabVIEW内部使用 */ typedef struct { int32_t status; int32_t code; char source[256]; } LVErrorCluster; /* 我们的函数声明 */ int32_t __stdcall CalculateMeanStdDev(const double inputArray[], int32_t arraySize, double *mean, double *stdDev, LVErrorCluster *errorIn, LVErrorCluster *errorOut); #ifdef __cplusplus } // extern C #endif #endif // __MyStatistics__我们来逐行解析extcode.h这是National Instruments提供的头文件定义了一些LabVIEW与C交互的基础数据类型和宏。调用方需要这个头文件或其内容才能正确编译。通常你需要将extcode.h和lv_prolog.h、lv_epilog.h等几个文件一并提供给调用方。LVErrorCluster这是LabVIEW错误簇在C中的结构体表示。status为布尔TRUE/FALSEcode为错误代码source为错误源。函数声明int32_t __stdcall CalculateMeanStdDev(...)int32_t返回值。LabVIEW生成的DLL函数通常返回一个int32_t类型的错误代码0表示成功负数表示失败。但请注意这个返回值与你配置的“返回类型”可能不同。在构建规范中你可以指定返回类型但LabVIEW强烈建议使用错误簇作为主要的错误报告机制返回值通常用于其他目的或保持为int32_t。__stdcall这就是我们选择的stdcall调用规范。const double inputArray[]对应我们的输入数组以常量指针形式传入防止函数内部修改。int32_t arraySize数组大小显式传递。double *mean, double *stdDev输出参数以指针形式传递函数将计算结果写入指针指向的内存。LVErrorCluster *errorIn, LVErrorCluster *errorOut错误输入和错误输出以指针传递。这是一种典型的“错误链”模式。数据类型映射表常用LabVIEW 数据类型推荐的C接口类型传递方式说明与注意事项双精度浮点数 (DBL)double值最简单直接传递。32位整数 (I32)int32_t值使用stdint.h中的类型保证跨平台一致性。布尔LVBoolean(int8_t)值LabVIEW定义的类型本质是8位整数。一维双精度数组const double array[]或double**数组数据指针输入用const double array[]并配一个int32_t size参数。输出非常复杂。通常需要调用方分配内存并传入指针double**或DLL返回一个由LabVIEW运行时管理的内存句柄需调用特定API释放。新手建议避免输出复杂数组。字符串char*或LStrHandleC字符串指针 / 字符串句柄简单字符串char*调用方分配缓冲区DLL填充。需约定缓冲区大小。复杂字符串使用LabVIEW字符串句柄(LStrHandle)但需要调用DSSetHandleSize等内存管理函数对调用方不友好。错误簇LVErrorCluster*指针使用LabVIEW预定义的结构体指针。调用方需要定义该结构体。簇简单自定义结构体指针需要手动定义与LabVIEW簇布局完全一致的C结构体并确保字节对齐。这是高级话题极易出错。实操心得在定义接口时遵循“KISS”原则Keep It Simple, Stupid。尽可能使用简单的标量类型int, double, bool作为输入和输出。如果必须传递数组优先作为输入参数。如果必须输出复杂数据可以考虑将其拆分为多个标量输出或者分多次调用。一个函数做一件事并把它做好。5. 在外部环境中调用LabVIEW生成的DLL生成DLL和头文件后就可以在其他环境中调用了。这里以C#和Python为例展示如何调用我们上面生成的CalculateMeanStdDev函数。5.1 在C#中调用C#通过平台调用P/Invoke技术来调用C DLL。using System; using System.Runtime.InteropServices; namespace LabVIEWDLLTest { class Program { // 定义与C结构体对应的错误簇 [StructLayout(LayoutKind.Sequential, CharSet CharSet.Ansi)] public struct LVErrorCluster { public int status; // LVBoolean 实际上是 int32_t public int code; [MarshalAs(UnmanagedType.ByValTStr, SizeConst 256)] public string source; } // 声明DLL函数 [DllImport(C:\Path\To\Your\MyStatistics.dll, CallingConvention CallingConvention.StdCall)] public static extern int CalculateMeanStdDev( [In] double[] inputArray, // 输入数组 int arraySize, // 数组大小 out double mean, // 输出平均值 out double stdDev, // 输出标准差 ref LVErrorCluster errorIn, // 错误输入可置空 out LVErrorCluster errorOut // 错误输出 ); static void Main(string[] args) { double[] data { 1.0, 2.0, 3.0, 4.0, 5.0 }; double mean 0, stdDev 0; LVErrorCluster errorIn new LVErrorCluster(); LVErrorCluster errorOut new LVErrorCluster(); // 调用DLL函数 int result CalculateMeanStdDev(data, data.Length, out mean, out stdDev, ref errorIn, out errorOut); if (result 0 errorOut.status 0) // 假设返回0且错误状态为0表示成功 { Console.WriteLine($平均值: {mean}, 标准差: {stdDev}); } else { Console.WriteLine($调用失败! 错误代码: {errorOut.code}, 错误源: {errorOut.source}); } } } }关键点[DllImport]属性指定DLL路径和调用约定(StdCall)。使用[StructLayout]确保C#结构体与C结构体的内存布局一致。数组参数作为[In] double[]传递C#会自动将其转换为指针。输出参数使用out关键字。错误簇作为结构体传递。5.2 在Python中调用使用ctypesPython的ctypes库是调用DLL的利器。import ctypes import numpy as np # 加载DLL my_dll ctypes.WinDLL(rC:\Path\To\Your\MyStatistics.dll) # 使用WinDLL因为调用约定是stdcall # 定义错误簇结构体 class LVErrorCluster(ctypes.Structure): _fields_ [ (status, ctypes.c_int32), (code, ctypes.c_int32), (source, ctypes.c_char * 256) ] # 设置函数原型参数类型和返回类型 my_dll.CalculateMeanStdDev.argtypes [ ctypes.POINTER(ctypes.c_double), # inputArray ctypes.c_int32, # arraySize ctypes.POINTER(ctypes.c_double), # mean (输出) ctypes.POINTER(ctypes.c_double), # stdDev (输出) ctypes.POINTER(LVErrorCluster), # errorIn ctypes.POINTER(LVErrorCluster) # errorOut ] my_dll.CalculateMeanStdDev.restype ctypes.c_int32 # 准备数据 data np.array([1.0, 2.0, 3.0, 4.0, 5.0], dtypenp.float64) array_size len(data) # 准备输出变量 mean ctypes.c_double(0.0) std_dev ctypes.c_double(0.0) error_in LVErrorCluster() error_out LVErrorCluster() # 调用DLL函数 # 注意numpy数组需要获取其ctypes数据指针并确保是连续的C顺序数组 result my_dll.CalculateMeanStdDev( data.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), array_size, ctypes.byref(mean), ctypes.byref(std_dev), ctypes.byref(error_in), ctypes.byref(error_out) ) if result 0 and error_out.status 0: print(f平均值: {mean.value}, 标准差: {std_dev.value}) else: print(f调用失败! 错误代码: {error_out.code}, 错误源: {error_out.source.decode(utf-8, errorsignore)})关键点使用ctypes.WinDLL加载DLL对应stdcall。用ctypes.Structure定义C结构体。argtypes和restype必须精确设置否则会导致调用崩溃。NumPy数组需要使用.ctypes.data_as(...)转换为对应的指针类型。输出参数需要先创建ctypes类型的变量然后使用ctypes.byref()传递其引用。6. 部署、依赖管理与常见问题排查6.1 部署清单将你的LabVIEW DLL交付给用户时绝不能只给一个.dll文件。一个完整的部署包应该包括DLL文件本身(MyStatistics.dll)。C语言头文件(MyStatistics.h)供C/C调用者使用。导入库文件(MyStatistics.lib)供C/C在链接时使用。必要的LabVIEW运行时引擎这是最重要的依赖项。你必须明确告知用户需要安装哪个版本如LabVIEW 2023 Runtime或更高版本。可以从NI官网免费下载。API文档一个简单的文档说明每个函数的功能、参数含义、返回值、错误代码。至少要把头文件里的函数声明和注释整理出来。调用示例提供至少一种语言如C#、Python的简单调用示例代码。6.2 常见错误与排查技巧在开发和调用过程中你几乎一定会遇到下面这些问题错误现象可能原因排查步骤与解决方案调用时程序崩溃Access Violation1. 参数数据类型不匹配。2. 指针传递错误如该用指针用了值。3. 数组大小参数与实际不符。4. 内存未正确分配输出缓冲区不足。1.仔细核对头文件确保调用方定义的每个参数类型、传递方式与头文件声明完全一致。2.使用调试器在C/C调用方代码中设置断点单步步入DLL函数看崩溃在哪一行。3.简化测试创建一个最简单的LabVIEW VI例如仅输入两个数返回和生成DLL并测试排除复杂逻辑干扰。4.检查数组确保输入数组是连续的输出数组指针指向有效的已分配内存。返回错误代码但LabVIEW错误簇无信息1. 错误簇参数传递方式错误如该用指针用了值。2. 调用方没有正确初始化或解析错误簇结构体。1. 确认在构建规范中错误簇的“传递方式”设置为“指针”。2. 在调用方代码中确保错误输入结构体被清零初始化并检查错误输出结构体的每个字段。DLL加载失败如“找不到指定模块”1. 目标系统缺少LabVIEW运行时引擎。2. 依赖的其它DLL如NI特定库缺失。3. DLL文件路径错误或位数不匹配32位 vs 64位。1.使用Dependency Walker这是一个经典工具打开你的DLL它能列出所有依赖项。检查是否有标红的、找不到的DLL特别是lvrt.dll系列LabVIEW运行时。2.确认位数你的LabVIEW是32位还是64位生成的DLL调用方程序也必须是对应的位数。混合使用必然失败。3.安装运行时确保目标机器安装了正确版本的LabVIEW运行时。函数调用成功但返回结果不对如全是0或NaN1. 输出参数指针未正确关联到LabVIEW控件。2. LabVIEW VI内部逻辑有误或存在未初始化的移位寄存器/反馈节点。3. 多线程调用时VI不是可重入的导致状态混乱。1.检查VI连线确保输出控件正确连接到了连接器窗格的输出端子。2.在LabVIEW中独立测试VI用测试面板输入数据看结果是否正确。3.检查VI属性右键点击VI图标-“属性”-“执行”确认“重入”设置是否与DLL构建规范中的“线程安全”设置匹配。如果不匹配在多线程调用时会出现不可预知的行为。生成DLL时编译报错1. VI中包含不支持生成代码的节点如某些UI控件、不支持的函数。2. 项目依赖缺失或路径错误。1. 查看编译错误详情LabVIEW会指出是哪个VI或节点有问题。常见的如“打开VI引用”在独立应用中受限。2. 确保所有用到的子VI、库文件都已添加到项目并且在“源文件设置”中正确包含。6.3 高级话题内存管理与线程安全内存管理这是DLL交互中最棘手的部分。基本原则是谁分配谁释放。如果DLL返回一个指向其内部数据的指针例如通过输出数组指针调用方绝对不能尝试去释放这个内存除非DLL明确提供了释放函数如DestroyArray。因为这块内存是由LabVIEW运行时引擎管理的。对于输入字符串如果DLL不会修改它最好声明为const char*。如果DLL需要修改或返回一个字符串最安全的方式是让调用方分配一个足够大的缓冲区然后将缓冲区和大小传给DLL。线程安全如果你的DLL函数可能被多个线程同时调用务必确保源VI设置为“可重入执行”在VI属性中设置。在DLL构建规范的“源文件设置”中为该VI选择“在任意线程中运行”。VI内部不能有未受保护的共享资源如全局变量、未加锁的硬件访问。对于硬件操作通常需要序列化访问这时“在UI线程中运行”反而是更安全的选择。7. 从“能用”到“好用”工程化实践与建议掌握了基本操作后如何让我们生成的DLL更健壮、更易用下面是一些进阶的工程化建议。7.1 设计清晰的API接口函数命名使用动词名词的形式如CalculateFFT,ReadDeviceTemperature清晰表达功能。单一职责一个函数只做一件事。不要设计一个ProcessData函数里面又做滤波又做傅里叶变换又保存文件。拆分成FilterSignal,ComputeFFT,SaveToFile等多个函数。统一的错误处理所有函数都使用相同的错误簇参数errorIn/errorOut。在DLL内部实现错误传递链。版本控制在头文件或通过一个单独的GetDLLVersion函数提供DLL的版本号便于调用方兼容性检查。7.2 创建全面的测试套件不要只依赖LabVIEW环境测试。应该创建跨语言的测试程序。单元测试用LabVIEW编写测试VI验证核心逻辑。集成测试用C#或Python编写测试脚本模拟真实调用场景测试数据边界空数组、极大值、NaN等、错误路径和压力测试多线程调用。自动化测试将上述测试集成到CI/CD流程中如Jenkins每次代码更新后自动生成DLL并运行测试。7.3 性能优化考量避免频繁调用每次调用DLL都有一定的开销。如果可能将一批数据的处理封装在一次调用中而不是循环调用处理单个数据点。数据布局对于大型数组确保数据在内存中是连续的C顺序LabVIEW默认是行优先与C一致。避免传递包含大量数据的复杂簇这会导致频繁的内存拷贝。异步操作对于耗时的操作如仪器初始化、大数据量采集可以考虑设计成异步模式。即提供一个StartAcquisition函数立即返回和一个IsAcquisitionDone或GetAcquisitionData函数。但这需要更复杂的DLL内部状态管理。7.4 文档与示例至上再好的DLL如果没有文档对使用者来说就是黑盒。除了头文件你应该提供README.md简要介绍DLL功能、依赖、构建方法。API文档使用Doxygen等工具从注释自动生成详细说明每个函数、参数、返回值、错误码。示例项目提供C、C#、Python等多种语言的完整、可编译/运行的示例项目。示例应覆盖基本调用、错误处理、数组传递等常见用例。变更日志记录每个版本的改动特别是接口不兼容的变更。最后也是我个人踩过最深的一个坑环境一致性。开发DLL的LabVIEW版本、运行时版本、甚至Windows的更新补丁都可能影响最终行为。务必在尽可能接近目标环境的环境中虚拟机是个好选择进行最终的集成测试。曾经有一个项目在开发机上一切正常到了客户工控机上就随机崩溃最后排查发现是客户机上某个Windows系统库的版本略旧与LabVIEW运行时的某个组件存在细微兼容性问题。从此以后沙盒环境测试成了我发布前的必备步骤。本文还有配套的精品资源点击获取
返回列表