Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling nicaiu.dll from python3

Solved!
Go to solution

Hello everyone, 

I am trying to use python with nicaiu.dll to do some measurements with myDAQ, 

I found a instruction from NI, http://www.ni.com/white-paper/8911/en/, I tried the example calling_daq_dll.py, it works very well with python 2.7, but something wrong with python 3.5,

by adding a channel to the task with the command:

dll = windll.LoadLibrary("nicaiu.dll")

dll.DAQmxCreateAIVoltageChan(taskHandle, physicalChannel, channelName, terminalConfig, minVal, maxVal, units, customScaleName)

it always shows the error: DAQmxErrorInvalidDeviceID,  -200220

 

Does anyone have a idea?  Is it a compatible problem with python 3 ?

 

Thanks.

Zhiwen

0 Kudos
Message 1 of 9
(4,597 Views)

Instead of writing your own C API Python wrappers, you may want to look at the nidaqmx Python package.

——
Brandon Streiff
ni.com/compactdaq · ni.com/daq
Message 2 of 9
(4,575 Views)

Thanks for your replay, with the package it works well, I just wonder, why it doesn't work with original dll calls.

0 Kudos
Message 3 of 9
(4,565 Views)

Did you update the physicalChannel variable? The example sets it to "dev1/ai0". On most PCI/USB NI DAQ devices the default name is "Devn", but with NI myDAQs the default name is "myDAQn". You'd probably need to change that to "myDAQ1/ai0".

——
Brandon Streiff
ni.com/compactdaq · ni.com/daq
0 Kudos
Message 4 of 9
(4,556 Views)

Yes, I changed it to "myDAQ1/ai0", but it doesn't work. 

 

The same code works well under python2 (except grammar difference for print).

 

0 Kudos
Message 5 of 9
(4,552 Views)

Hmm, I'm not sure then. My python-fu is not strong, and I don't understand why that particular call would have different behavior between python2 and python3. (Perhaps some slight change happened to the way that ctypes marshals parameters?)

——
Brandon Streiff
ni.com/compactdaq · ni.com/daq
0 Kudos
Message 6 of 9
(4,544 Views)

Anyway, thanks for your replies.

0 Kudos
Message 7 of 9
(4,542 Views)
Solution
Accepted by topic author heyutu
I found the solution online: in python 2: physicalChannel = "myDAQ1/ai0" in python 3: physicalChannel = b"myDAQ1/ai0" the string need to convert to byte format with a 'b' prefix.
0 Kudos
Message 8 of 9
(4,521 Views)

As you already found out you have to pass the name as a bytes object. Here a little bit more explanation why:

 

The signature of the function you called is:

int32 __CFUNC     DAQmxCreateAIVoltageChan       (TaskHandle taskHandle, const char physicalChannel[], const char nameToAssignToChannel[], int32 terminalConfig, float64 minVal, float64 maxVal, int32 units, const char customScaleName[]);

so it expects a `const char *` for the physicalChannel parameter, which in ctypes is represented as a `c_char_p` object.

 

Between Python 2 and Python 3, the corresponding "native" python type for `c_thar_p` changed:

 - In Python 2.7 `c_char_p` was equivalent to the python `string` object which has 8bit characters in Py2.7.

 - In Python 3 `c_char_p` is equivalent to the python `bytes` object. The `string` type is equivalent to `c_wchar_p` (note the `w` which means it is a 16bit character pointer).

 

When you write in python a string `"blablabla"` (without any prefixes) it will have the `string` type by default. So when you wrote the string in Py2.7 it automatically already had the right type (8bit characters). But in Python 3 the default string has 16bit characters, so you either have to explicitly produce a bytes object (by adding the prefix `b` to  the string) or you have to convert the `string` to a bytes object (e.g. `myBlaBla.encode()`)

 

See also the tables for Python 2.7 and Python 3:

https://docs.python.org/2.7/library/ctypes.html#fundamental-data-types

https://docs.python.org/3/library/ctypes.html#fundamental-data-types

Message 9 of 9
(4,339 Views)