Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

How Can I Use The NI-DAQmx ANSI C Function Library With GCC (on Windows)?

Hi,

I am using an NI 6220 (M-Series) DAQ Device and tried to compile one of the examples from
"National Instruments\NI-DAQ\Examples\DAQmx ANSI C"
with gcc (using cygwin and Windows XP):

First I copied the example "Acq-IntClk.c", "NIDAQmx.h" and "NIDAQmx.lib" into one directory, then I ran gcc

$ gcc -mno-cygwin -Wall Acq-IntClk.c NIDAQmx.lib -o Acq-IntClk.exe

but this failed to link and gcc complained about several undefined references to functions like
`DAQmxCreateTask@8', `DAQmxCreateAIVoltageChan@40', `DAQmxCfgSampClkTiming@32', `DAQmxStartTask@4', ...

It seems that this problem has to do with the "NIDAQmx.lib" library, which is for MS Visual C++ as it
is in the "National Instruments\NI-DAQ\DAQmx ANSI C Dev\lib\msvc" directory.
(And I had no problems with compiling and linking the same example using Visual C++.)

I also found a similar topic dealing with Borland C in the knowledge base:
"How Can I Use The NI-DAQmx ANSI C Function Library With Borland C and Delphi?"
http://digital.ni.com/public.nsf/websearch/B09727F89DA3A06C86256F430071D88E?OpenDocument
where an NIDAQmx.lib file for Borland C is available.

Is there also an NIDAQmx.lib for gcc available? Or does any other solution exist for my problem?

Thanks in advance
Jens
0 Kudos
Message 1 of 43
(17,684 Views)
The following seems to work:
open up NIDAQmx.h with your editor(or dl attatchment if your lazy), make all #define's at the top few lines that have something to do with cstdcall__ or whatever crap blank, that is
#define CFUNC stdcall__
to
#define CFUNC
Repeat for the following few lines that look similiar.
, then do a find and replace for __int64 and replace it with long long, same for __uint64.

Then do a search/locate for nicaiu.dll, you'll be linking with it.

For any NI software engineers or support... is it really so hard to add support for another compiler? NIDAQmxbase works fine with gcc and links fine without any crap but unfortunately not all cards seem to be supported with nidaqmxbase and it cannot be used to interface with NIDAQmx... I've many questions with that but w/e. It was a real *itch to find out how to do this and only because a few macros in NIDAQmx.h and something to do with NIDAQmx.lib not actually having the symbols needed... I can only surmize it pointed to nicaiu.dll somehow. Please add support for gcc.

ps, attached is the NIDAQmx.h I'm using atm, I've yet to have problems.
Message 2 of 43
(17,618 Views)

@Jason Newton wrote:
is it really so hard to add support for another compiler?



For any given compiler, it's not that hard. The trouble is in the testing and the customer support. It's hard to justify spending time testing and training support folks on supporting DAQmx with a compiler that not a whole lot of customers need to use.

What we we'll probably end up doing is the following: as we get requests for certain compilers, we'll add KnowledgeBase articles explaining how to get DAQmx working with them, but we won't officially support them. If we get enough requests for a certain compiler, we'll consider adding official support for it.

Good luck,
Joe
0 Kudos
Message 3 of 43
(17,607 Views)
The NIDAQmx.lib library does have the symbols that are needed. However, since you changed the definition of __CFUNC, your application is looking for different symbols. The definition of __CFUNC is important; it is specifying the calling convention to be standard call rather than C call. Your changes to NIDAQmx.h change the specification of the calling convention and, in this case, the symbol name as well.

A more compatible approach would be to leverage gcc's attributes to specify the calling convention. #define __CFUNC attribute((stdcall)) and #define CFUNC_C attribute((cdecl)) may work. If they do, you should be able to link against NIDAQmx.lib as intended.

geoff
--
Geoffrey Schmit
Fermi National Accelerator Laborary
Message 4 of 43
(17,601 Views)
Thanks for your replies!
I've tried your suggestions and I also got some very usefull hints.

1) Jason's method seems to work fine, but I'm concerned, that this method might mess up the stack. As I understood __cdecl means, that the calling function removes the parameters from the stack after the function returned, while __stdcall means, that the function removes the parameters itself. gcs already pointed out that this calling convention is important.

2) gcs' suggestion of using attribute does not work (at least I wasn't able to find a difference, when using __attribute__((stdcall)) instead of __stdcall), but I had no experience with these compiler details so far.

3) a new approach to the problem: gcs also stated that "the NIDAQmx.lib library does have the symbols that are needed". This is surely true, but there seem to be different naming (or "decoration") conventions, as described at
Stdcall and DLL tools of MSVC and MinGW
In short: the internal represantations of function names have different "decorations". Especially gcc expects, that "@nn" (where nn is the size of all parameters in bytes) is appended to stdcall function names, while the MSVC dll uses the plain name without the "@nn".

Using Microsoft DLL's when Compiling Cygwin or Mingw describes a workaround. Basically one has to write a .def file and then create a library with the "right" names:

Setup:
------
I have copied all necessary files into the current directory:
NIDAQmx.h (from NI-DAQ\DAQmx ANSI C Dev\include)
NIDAQmx.lib (from NI-DAQ\DAQmx ANSI C Dev\lib\msvc)
nicaiu.dll (from C:\WINDOWS\system32)
together with one of the examples
Acq-IntClk.c (from NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Voltage\Acq-Int Clk)

Procedure:
----------
1) call gcc to find the missing function names:
$ gcc Acq-IntClk.c -o Acq-IntClk.exe NIDAQmx.lib
gcc complains about undefined references as before.

2) put the names of the functions into a .def file (e.g. "mynicaiu.def"). The file should look like this (without -START- and --END-- lines, of course):
---------------START---------------
LIBRARY nicaiu.dll
EXPORTS
DAQmxCreateTask@8
DAQmxCreateAIVoltageChan@40
DAQmxCfgSampClkTiming@32
DAQmxStartTask@4
DAQmxReadAnalogF64@36
DAQmxGetExtendedErrorInfo@8
DAQmxStopTask@4
DAQmxClearTask@4
----------------END----------------

3) build a library (e.g. "libmynicaiu.a") from nicaiu.dll and mynicaiu.def:
$ dlltool --input-def mynicaiu.def --dllname nicaiu.dll --output-lib libmynicaiu.a -k

4) use libmynicaiu.a instead of NIDAQmx.lib for compilation with gcc:
$ gcc Acq-IntClk.c -o Acq-IntClk.exe libmynicaiu.a
This will finally create Acq-IntClk.exe, which seems to work! But I haven't done extensive tests yet and I am really not a compiler/linker expert.

The advantage of this method is, that there is no need to change the calling conventions in "NIDAQmx.h".
The disadvantage is, that one has to find out the right function names, which must be added to mynicaiu.def. The problem here is the right number nn in the appended "@nn".


The easiest solution would surely be a library, which is built by National Instruments. Perhaps it is really just a matter of the "right" linker option? A KnowledgeBase article solving this problem and supplying such a library would be great!


Sincerely,
Jens
Message 5 of 43
(17,589 Views)
My approach didn't work so well, something went bad, probably having to do with the stdcall stuff. I'd get segfaults in weird places for code that worked perfectly fine in nidaqmxbase, the examples from NI also would segfault.

I had no luck with any of gcc's attributes to link successfully. I had thought it didn't contain the needed symbols because when trying to view simples via objdump, I'd always get nicaiu.dll: permission denied and linking with nicaiu.dll worked...

Using stadels procedures did link but programs would not run correctly either. Instant segfaults as the call to any daqmx function is made.

A KnowledgeBase article or something would be great!
0 Kudos
Message 6 of 43
(17,566 Views)

@stadel wrote:
1) Jason's method seems to work fine, but I'm concerned, that this method might mess up the stack. As I understood __cdecl means, that the calling function removes the parameters from the stack after the function returned, while __stdcall means, that the function removes the parameters itself. gcs already pointed out that this calling convention is important.


Yes, this is correct. See, this description of stdcall for more information. Also note that, according to this site, there are subtle difference between Visual C++ and gcc's implementation of stdcall. These could lead to problems....



2) gcs' suggestion of using attribute does not work (at least I wasn't able to find a difference, when using __attribute__((stdcall)) instead of __stdcall), but I had no experience with these compiler details so far.


How is it not working? Are you getting compiler errors? Linker errors? I don't have gcc for Windows, so I haven't tried this myself. However, I believe that gcc for Windows does support specifying that a function should be called with the stdcall calling conventions.



3) a new approach to the problem: gcs also stated that "the NIDAQmx.lib library does have the symbols that are needed". This is surely true, but there seem to be different naming (or "decoration") conventions, as described at
Stdcall and DLL tools of MSVC and MinGW
In short: the internal represantations of function names have different "decorations". Especially gcc expects, that "@nn" (where nn is the size of all parameters in bytes) is appended to stdcall function names, while the MSVC dll uses the plain name without the "@nn".

Using Microsoft DLL's when Compiling Cygwin or Mingw describes a workaround. Basically one has to write a .def file and then create a library with the "right" names:


One clarification: As noted on the Stdcall and DLL tools of MSVC and MinGW page, the format of the symbol names depends on how the DLL is built (DEF file versus dllexport). The NIDAQmx.lib import library does have the proper name decorations and should be what gcc expects. If you invoke dumpbin /exports nidaqmx.lib, the symbols are prefixed by an underscore and appended with the size of their parameters (e.g., _DAQmxWriteRaw@32). In fact, the NIDAQmx.lib is the import library for the nicaiu DLL. So, you shouldn't need to create your libmynicaiu import library. NIDAQmx.lib is just such a library.



1) call gcc to find the missing function names:
$ gcc Acq-IntClk.c -o Acq-IntClk.exe NIDAQmx.lib
gcc complains about undefined references as before.


What is the output from this command? If gcc is interpreting the DAQmx functions as stdcall, I would expect this to work.

Thanks!

geoff
--
Geoffrey Schmit
Fermi National Accelerator Laborary
Message 7 of 43
(17,559 Views)
I wasn't aware of the subtle differences between Visual C++ and gcc's implementation of stdcall, but there is a at least a good chance that it works for C. I've read that Cygwin and MinGW allow to use Windows libraries, which make use of stdcall.

Your suggestion of using __attribute__((stdcall)) instead of __stdcall is completely right! Meanwhile I have even found the following in _mingw.h (together with the statement "/* All the headers include this file. */"):
# ifndef __stdcall
# define __stdcall __attribute__((stdcall))
# endif

What I wanted to say was, that it had not make any difference for my problem, because I got the same (linker) errors in both cases:

$ gcc Acq-IntClk.c -o Acq-IntClk.exe NIDAQmx.lib
Temp/ccQBbaaa.o(.text+0xc7):Acq-IntClk.c: undefined reference to `DAQmxCreateTask@8'
Temp/ccQBbaaa.o(.text+0x104):Acq-IntClk.c: undefined reference to `DAQmxCreateAIVoltageChan@40'
Temp/ccQBbaaa.o(.text+0x13a):Acq-IntClk.c: undefined reference to `DAQmxCfgSampClkTiming@32'
Temp/ccQBbaaa.o(.text+0x150):Acq-IntClk.c: undefined reference to `DAQmxStartTask@4'
Temp/ccQBbaaa.o(.text+0x189):Acq-IntClk.c: undefined reference to `DAQmxReadAnalogF64@36'
Temp/ccQBbaaa.o(.text+0x1c4):Acq-IntClk.c: undefined reference to `DAQmxGetExtendedErrorInfo@8'
Temp/ccQBbaaa.o(.text+0x1d8):Acq-IntClk.c: undefined reference to `DAQmxStopTask@4'
Temp/ccQBbaaa.o(.text+0x1e6):Acq-IntClk.c: undefined reference to `DAQmxClearTask@4'

(I have cut off a part of the pathname of the temporary file from the output)

I still don't understand this (but I admit, that I haven't dealed in detail with DLLs before). gcc doesn't find "DAQmxCreateTask@8" (just as an example from the output above), when using NIDAQmx.lib. The output of dumpbin /exports nidaqmx.lib contains "_DAQmxCreateTask@8", as you already pointed out. To my surprise, the output of dumpbin /exports libmynicaiu.a also contains "_DAQmxCreateTask@8"! (libmynicaiu.a is build with dlltool as desribed in my last mail.)
BUT: dumpbin /exports nicaiu.dll reveals only "DAQmxCreateTask" (without any decoration!). It seems, that my home-made "libmynicaiu.a" contains additional information that allows gcc (and the linker called by gcc) to locate the functions inside nicaiu.dll. But this is just a guess!

At least now I know, that I can get the needed function names (nearly 2000) with a simple dumpbin /exports nidaqmx.lib. This helps a lot.

Thanks!
Jens
0 Kudos
Message 8 of 43
(17,533 Views)
I just installed cygwin/gcc to try this out myself, and I ran into very similar problems (undefined reference to _DAQmxCreateTask@8 etc.)

I'm strongly suspecting that gcc/ld is unable to use the NIDAQmx.lib import library. At least, in gcc for Linux, there is no concept of an import library (you link against a static library, *.a, or against a shared library, *.so).

I used CVI to generate dynamic DLL wrapper code from the NIDAQmx.h file. The resulting file, NIDAQmx.c, can be compiled into your program to resolve the DAQmx entry points.

The only caveat here is that the generated NIDAQmx.c file doesn't implement the variable argument functions; e.g., DAQmxGetTaskAttribute (TaskHandle taskHandle, int32 attribute, void *value, ...)

Good luck,
Joe

P.S. I generated this wrapper file using the NI-DAQ 7.4 version of NIDAQmx.h. If you use an earlier version of NI-DAQ, you may get runtime errors due to missing exports in nicaiu.dll.

Message Edited by JoeSavage on 05-08-2005 10:18 AM

Message 9 of 43
(17,522 Views)
You Sir, are great!
Edit: Everything works now, stable and all.

Message Edited by Jason Newton on 05-08-2005 04:14 PM

0 Kudos
Message 10 of 43
(17,508 Views)