DAQmx Base Programming in C#, VB .NET, and VB 6.0

Updated Dec 23, 2023

Reported In

Driver

  • NI-DAQmx
  • NI-DAQmx Base 15.0

Programming Language

  • C# .NET
  • Visual Basic .NET

Issue Details

Can I program a DAQmx Base device in C#, VB .NET, or VB 6.0?

Solution

Note: NI-DAQmx Base is compatible with macOS 10.14 and earlier versions and starting 2018, NI-DAQmx for Linux is included with the NI Linux Device Drivers. Please check compatibility for Windows, Linux, and macOS for supported versions of this driver. For more information, please read the End-of-Life Announcement for DAQmx Base Driver.

You can call DAQmx Base functions in these languages. However, DAQmx Base is only officially supported in LabVIEW and C. Because of this, you'll need to directly call the DAQmx Base DLL if you plan to use a different language. The following examples demonstrate calling the DAQmx Base DLL directly.

[C#]
using System;
using System.Runtime.InteropServices;
using TaskHandle = System.UInt32;
public class LibWrap
{
    // C# doesn't support varargs so all arguments must be explicitly defined.
    // CallingConvention.Cdecl must be used since the stack is
    // cleaned up by the caller.
    [DllImport("nidaqmxbase.dll", CharSet=CharSet.Ansi,
                CallingConvention=CallingConvention.Cdecl)]
    public static extern int DAQmxBaseCreateTask (
                string taskName, out TaskHandle taskHandle);

    [DllImport("nidaqmxbase.dll", CharSet=CharSet.Ansi,
                CallingConvention=CallingConvention.Cdecl)]
    public static extern int DAQmxBaseCreateAIThrmcplChan (
                TaskHandle taskHandle, string physicalChannel, 
                string nameToAssignToChannel, double minVal, double maxVal, 
                int units, int thermocoupleType, int cjcSource, double cjcVal, 
                string cjcChannel);
}

public class App
{
    public static void Main()
    {
        TaskHandle taskHandle;
        LibWrap.DAQmxBaseCreateTask("", out taskHandle) );
        LibWrap.DAQmxBaseCreateAIThrmcplChan(taskHandle, "/Dev1/ai0", "", 0,
                                    10, DAQmx_Val_DegC, DAQmx_Val_K_Type_TC, 
                                    DAQmx_Val_BuiltIn, 0, "") );
    }
}

[VB .NET]
Imports System
Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices
Imports TaskHandle = System.UInt32
Public Class LibWrap
    ' Visual Basic does not support varargs, so all arguments must be
    ' explicitly defined. CallingConvention.Cdecl must be used since the
    ' stack is cleaned up by the caller.
    <DllImport("nidaqmxbase.dll", CallingConvention:= _
               CallingConvention.Cdecl)> Public Shared Function _
               DAQmxBaseCreateTask(ByVal taskName As String, _
               ByRef taskHandle As TaskHandle) As Integer
    End Function

    <DllImport("nidaqmxbase.dll", CallingConvention := _
                CallingConvention.Cdecl)> Public Shared Function _
                DAQmxBaseCreateAIVoltageChan(ByVal taskHandle _
                As TaskHandle, ByVal physicalChannel As String, _
                ByVal nameToAssignToChannel As String, ByVal terminalConfig _
                As Integer, ByVal minVal As Double, ByVal maxVal As Double, _
                ByVal units As Integer, ByVal customScaleName As String) _
  As Integer
    End Function
End Class 'LibWrap

Public Class App
    Public Shared Sub Main()
        Dim taskHandle As TaskHandle = Convert.ToUInt32(0)
        LibWrap.DAQmxBaseCreateTask("", taskHandle)
        LibWrap.DAQmxBaseCreateAIVoltageChan(taskHandle, "/Dev1/ai0", "", _
        DAQmx_Val_Cfg_Default, 0, 10, DAQmx_Val_Volts, Nothing)
    End Sub 'Main
End Class 'App

[VB 6.0]
The DAQmx Base DLL cannot be directly called from VB 6.0, because the DLL exports functions using the cdecl calling convention. VB 6.0 only supports stdcall. The only way to get around this is to create a wrapper C DLL that calls the functions using cdecl and exports them again using stdcall. A wrapper C DLL for DAQmx Base 1.5 and a simple example demonstrating how to use it are attached. Please follow the instructions of README.txt before running the example.

Additional Information

Using cdecl vs. stdcall:

When calling a DLL, the calling convention (cdecl vs. stdcall in this case) must be the same for the function calling the DLL and the DLL itself. 

In the cdecl calling convention, the calling function is responsible for cleaning up the stack. By contrast, the function being called cleans up the stack in stdcall. Functions in cdecl can also have a variable number of arguments, but stdcall does not support variable numbers of arguments.

If you try to use stdcall to call a function exported in cdecl, both the calling function and the called DLL function will assume that the other is going to clean up the stack. The code will run, but each call will consume more stack space because neither of the functions will ever remove data from the stack.

National Instruments recommends using stdcall for any functions exported from a DLL unless you need to use a variable number of arguments. Visual Basic and other non-C Windows programs will expect DLL functions to be exported with stdcall.

DAQmx support:
Many NI DAQ products that originally only supported DAQmx Base have been upgraded to include full DAQmx support. Check your device's datasheet for detailed information about driver support.