Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

EveryNSamplesEvent Callback Interop

We a library using the ANSI-C interfaces, and it is in C# (yes, there are C# DAQmx libraries, but they don't work on Linux / .NetStandard 2.1).  So, we've written a wrapper using PInvoke / Interop in C# and it's been working great.  Cross-platform, C# code commanding NI-DAQ devices.

 

But we've run into an issue on how to work with the EveryNSamplesEventCallback and how to marshal that across.  We've tried passing straight as a IntPtr, and so on.  Below is how we're currently implemented, and we never receive an error.  But it doesn't every get into the callback, and it actually holds onto it somewhere (in a Daqmx thread I assume), and really ends up bringing down the whole system (keeps locks on all the files, unkillable process; must reboot to fix it).

 

        [DllImport("nicaiu", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern int DAQmxRegisterEveryNSamplesEvent(IntPtr task, Int32 everyNsamplesEventType, UInt32 nSamples, UInt32 options, EveryNSamplesCallback callbackFunction, IntPtr callbackData);

   
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate Int32 EveryNSamplesCallback(IntPtr taskHandle, Int32 everyNsamplesEventType, UInt32 nSamples, IntPtr callbackData);
            func = new EveryNSamplesCallback(Test2Callback);

 

tmp += ChkForError(DAQmxRegisterEveryNSamplesEvent(taskHandle_DAT, DAQmx_Val_Transferred_From_Buffer, 104, 0 , func, new IntPtr()));

 

        public Int32 Test2Callback(IntPtr taskHandle, Int32 everyNsamplesEventType, UInt32 nSamples, IntPtr callbackData)
        {
            Console.WriteLine("CALLBACK!!");
            return 0;
        }

 

 

We've tried static functions and are continually playing with all of the various Marshal parameters, but haven't gotten anywhere.

 

Here's the relevant section of the NIDaqmx.h:

typedef int32 (CVICALLBACK *DAQmxEveryNSamplesEventCallbackPtr)(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData);

int32 __CFUNC     DAQmxRegisterEveryNSamplesEvent(TaskHandle task, int32 everyNsamplesEventType, uInt32 nSamples, uInt32 options, DAQmxEveryNSamplesEventCallbackPtr callbackFunction, void *callbackData);

 

The actual function is:

 

CVICALLBACK is deifned as __cdecl in NIDaqmx.h:

#define CVICDECL        __cdecl
#define CVICALLBACK     CVICDECL

 

0 Kudos
Message 1 of 2
(1,807 Views)

For anyone finding this, you also need to tag the Callback to Marshal as an unmanaged function pointer.  For some reason I just assumed that tagging the delegate would make it marshal that way, but there's a need to be explicit.

 

   public static extern int DAQmxRegisterEveryNSamplesEvent(IntPtr task, Int32 everyNsamplesEventType, UInt32 nSamples, UInt32 options,[MarshalAs(UnmanagedType.FunctionPtr)]EveryNSamplesCallback callbackFunction, IntPtr callbackData);

 

0 Kudos
Message 2 of 2
(1,748 Views)