Discussion:
How Can I Use The NI-DAQmx ANSI C Function Library With GCC (on Windows)?
(too old to reply)
stadel
2005-03-21 21:11:19 UTC
Permalink
Hi,<br><br>I am using an NI 6220 (M-Series) DAQ Device and tried to compile one of the examples from<br>"National Instruments\NI-DAQ\Examples\DAQmx ANSI C"<br>with gcc (using cygwin and Windows XP):<br><br>First I copied the example "Acq-IntClk.c", "NIDAQmx.h" and "NIDAQmx.lib" into one directory, then I ran gcc<br><br>$ gcc -mno-cygwin -Wall Acq-IntClk.c NIDAQmx.lib -o Acq-IntClk.exe<br><br>but this failed to link and gcc complained about several undefined references to functions like<br>`***@8', `***@40', `***@32', `***@4', ...<br><br>It seems that this problem has to do with the "NIDAQmx.lib" library, which is for MS Visual C++ as it<br>is in the "National Instruments\NI-DAQ\DAQmx ANSI C Dev\lib\msvc" directory.<br>(And I had no problems with compiling and linking the same example using Visual C++.)<br><br>I also found a similar topic dealing with Borland C in the knowledge base:<br>"How Can I Use The NI-DAQmx ANSI C Function Library With Borland C and Delphi?"<br>http://digital.ni.com/public.nsf/websearch/B09727F89DA3A06C86256F430071D88E?OpenDocument<br>where an NIDAQmx.lib file for Borland C is available.<br><br>Is there also an NIDAQmx.lib for gcc available? Or does any other solution exist for my problem?<br><br>Thanks in advance<br>Jens
Jason Newton
2005-05-04 06:40:52 UTC
Permalink
The following seems to work:<br>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 <br>#define CFUNC stdcall__<br>to <br>#define CFUNC<br>Repeat for the following few lines that look similiar.<br>, then do a find and replace for __int64 and replace it with long long, same for __uint64.<br><br>Then do a search/locate for nicaiu.dll, you'll be linking with it. <br><br>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.<br><br>ps, attached is the NIDAQmx.h I'm using atm, I've yet to have problems.


NIDAQmx.h:
http://forums.ni.com/attachments/ni/250/12110/1/NIDAQmx.h
stadel
2005-05-05 15:11:06 UTC
Permalink
Thanks for your replies!<br>I've tried your suggestions and I also got some very usefull hints.<br><br>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.<br><br>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.<br><br>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<br><a href="http://www.geocities.com/yongweiwu/stdcall.htm" target=_blank>Stdcall and DLL tools of MSVC and MinGW</a><br>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".<br><br><a href="http://www.emmestech.com/software/cygwin/pexports-0.43/moron1.html" target=_blank>Using Microsoft DLL's when Compiling Cygwin or Mingw</a> describes a workaround. Basically one has to write a .def file and then create a library with the "right" names:<br><br>Setup: <br>------<br>I have copied all necessary files into the current directory:<br>NIDAQmx.h (from NI-DAQ\DAQmx ANSI C Dev\include)<br>NIDAQmx.lib (from NI-DAQ\DAQmx ANSI C Dev\lib\msvc) <br>nicaiu.dll (from C:\WINDOWS\system32)<br>together with one of the examples<br>Acq-IntClk.c (from NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Voltage\Acq-Int Clk)<br><br>Procedure:<br>----------<br>1) call gcc to find the missing function names:<br>$ gcc Acq-IntClk.c -o Acq-IntClk.exe NIDAQmx.lib<br>gcc complains about undefined references as before.<br><br>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):<br>---------------START---------------<br>LIBRARY nicaiu.dll<br>EXPORTS<br> ***@8<br> ***@40<br> ***@32<br> ***@4<br> ***@36<br> ***@8<br> ***@4<br> ***@4<br>----------------END----------------<br><br>3) build a library (e.g. "libmynicaiu.a") from nicaiu.dll and mynicaiu.def:<br>$ dlltool --input-def mynicaiu.def --dllname nicaiu.dll --output-lib libmynicaiu.a -k<br><br>4) use libmynicaiu.a instead of NIDAQmx.lib for compilation with gcc:<br>$ gcc Acq-IntClk.c -o Acq-IntClk.exe libmynicaiu.a<br>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.<br><br>The advantage of this method is, that there is no need to change the calling conventions in "NIDAQmx.h".<br>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".<br><br><br>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!<br><br><br>Sincerely,<br>Jens
gcs
2005-05-06 13:10:58 UTC
Permalink
<blockquote><hr>stadel wrote:<br>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.<br><hr></blockquote><br>Yes, this is correct. See, <a href="http://www.programmersheaven.com/2/Calling-conventions#stdcall" target=_blank>this</a> 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....<br> <br><blockquote><hr><br>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.<br><hr></blockquote><br>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.<br><br><blockquote><hr><br>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<br><a href="http://www.geocities.com/yongweiwu/stdcall.htm" target=_blank>Stdcall and DLL tools of MSVC and MinGW</a><br>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".<br><br><a href="http://www.emmestech.com/software/cygwin/pexports-0.43/moron1.html" target=_blank>Using Microsoft DLL's when Compiling Cygwin or Mingw</a> describes a workaround. Basically one has to write a .def file and then create a library with the "right" names:<br><hr></blockquote><br>One clarification: As noted on the <a href="http://www.geocities.com/yongweiwu/stdcall.htm" target=_blank>Stdcall and DLL tools of MSVC and MinGW</a> 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 <code>dumpbin /exports nidaqmx.lib</code>, the symbols are prefixed by an underscore and appended with the size of their parameters (e.g., ***@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.<br><br><blockquote><hr><br>1) call gcc to find the missing function names:<br>$ gcc Acq-IntClk.c -o Acq-IntClk.exe NIDAQmx.lib<br>gcc complains about undefined references as before.<br><hr></blockquote><br>What is the output from this command? If gcc is interpreting the DAQmx functions as stdcall, I would expect this to work.<br><br>Thanks!<br><br>geoff
stadel
2005-05-07 11:10:58 UTC
Permalink
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.<br><br>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. */"):<br><code># ifndef __stdcall<br># define __stdcall __attribute__((stdcall))<br># endif</code><br>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: <br><br><code>$ gcc Acq-IntClk.c -o Acq-IntClk.exe NIDAQmx.lib<br>Temp/ccQBbaaa.o(.text+0xc7):Acq-IntClk.c: undefined reference to `***@8'<br>Temp/ccQBbaaa.o(.text+0x104):Acq-IntClk.c: undefined reference to `***@40'<br>Temp/ccQBbaaa.o(.text+0x13a):Acq-IntClk.c: undefined reference to `***@32'<br>Temp/ccQBbaaa.o(.text+0x150):Acq-IntClk.c: undefined reference to `***@4'<br>Temp/ccQBbaaa.o(.text+0x189):Acq-IntClk.c: undefined reference to `***@36'<br>Temp/ccQBbaaa.o(.text+0x1c4):Acq-IntClk.c: undefined reference to `***@8'<br>Temp/ccQBbaaa.o(.text+0x1d8):Acq-IntClk.c: undefined reference to `***@4'<br>Temp/ccQBbaaa.o(.text+0x1e6):Acq-IntClk.c: undefined reference to `***@4'</code><br>(I have cut off a part of the pathname of the temporary file from the output)<br><br>I still don't understand this (but I admit, that I haven't dealed in detail with DLLs before). gcc doesn't find "***@8" (just as an example from the output above), when using NIDAQmx.lib. The output of <code>dumpbin /exports nidaqmx.lib</code> contains "***@8", as you already pointed out. To my surprise, the output of <code>dumpbin /exports libmynicaiu.a</code> also contains "***@8"! (libmynicaiu.a is build with dlltool as desribed in my last mail.)<br>BUT: <code>dumpbin /exports nicaiu.dll</code> 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!<br><br>At least now I know, that I can get the needed function names (nearly 2000) with a simple <code>dumpbin /exports nidaqmx.lib</code>. This helps a lot.<br><br>Thanks!<br>Jens
JoeSavage
2005-05-08 15:41:07 UTC
Permalink
I just installed cygwin/gcc to try this out myself, and I ran into very similar problems (undefined reference to ***@8 etc.)<br><br>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).<br><br>I used CVI to generate dynamic DLL wrapper code from the NIDAQmxh file. The resulting file, NIDAQmx.c, can be compiled into your program to resolve the DAQmx entry points.<br><br>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, ...)<br><br>Good luck,<br>Joe<br><br>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.<p>Message Edited by JoeSavage on <span class=date_text>05-08-2005</span> <span class=time_text>10:18 AM</span>


NIDAQmx.c:
http://forums.ni.com/attachments/ni/250/12206/1/NIDAQmx.c
Tree
2006-03-14 17:13:59 UTC
Permalink
Hello,

Thanks for the zip file. One thing that was not mentioned was the need
to add "#include &lt;windows.h&gt;" to the sample source code.

Thanks again.

Jeff
Pablo2565
2006-03-27 18:40:11 UTC
Permalink
My guess is that you are using a unix-like shell to perform this step of MSVC_to_gcc.txt:

dlltool -d nidaqmx.def -D \WINDOWS\system32\nicaiu.dll -l libnidaqmx.a -k

but failing to escape the backslashes correctly.

Try running this command under the Win32 command processor cmd.exe.

In fact if you have the line

LIBRARY nicaiu.dll

at the top of your .def, and %SystemRoot%\system32 on your %PATH%, you shouldn't need the -D argument at all.

-- Pablo2565
Pablo2565
2006-04-28 17:40:10 UTC
Permalink
Simple solution:

move
#include &lt;stdio.h&gt;
before
#include &lt;NIDAQmx.h&gt;

in the example .c file.

Complex solution:

hack NIDAQmx.h to do something smarter than
#ifdef __linux__
when creating 64 bit typedefs.
Nazgul
2008-05-06 22:10:08 UTC
Permalink
Thanks to all of you in this thread.&nbsp; Without official gcc support from NI, these postings have proven to be an invaluable resource.I had to do things a bit differently, so here's the details:1) copy nidaqmxbase.dll to a working directory, in my case:C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\lib\gcc2) Execute pexports to generate .def file:http://www.emmestech.com/moron_guides/moron1.html has useful info on using microsoft dlls with cygwin/mingw/cygdrive/c/Program\ Files/pexports-0.43/bin/pexports.exe nidaqmxbase.dll | sed 's/^_//' &gt; nidaqmxbase.def3) Use dlltool to create libdaqmxbase.adlltool --input-def nidaqmxbase.def --dllname nidaqmxbase.dll --output-lib libnidaqmxbase.a -k4) Link and build with the appropriate directories -I and -L in your Makefile, or copy the .a to a directory in your path- I/cygdrive/c/"Program Files"/"National Instruments"/"NI-DAQmx Base"/Include-L"/cygdrive/c/Program Files/National Instruments/NI-DAQ/DAQmx ANSI C Dev/lib/gcc"(hmm, just noticed I'm including the header from Base, and put my .a in NI-DAQ, might edit this post later if I clean things up)5) I had to switch the driver in the System-&gt;Hardware-&gt;Device Manager to NI-VISA USB Devices-&gt;NI USB-6501 24-line Digital IOI was getting DAQmxBase Error -200220: &lt;err&gt;Device identifier is invalid.&nbsp; Then I found the following link.&nbsp; After this, things seem to be working fairly swimmingly.http://digital.ni.com/public.nsf/allkb/64BA7A1D64D3D5518625726D0066A780?OpenDocumentThough I still get warnings about uInt32 and int32 -- I think a couple of typedefs should take care of it.Please let me know if you find some glaring error, or have a better solution.
Loading...