ni.com is currently undergoing scheduled maintenance.

Some services may be unavailable at this time. Please contact us for help or try again later.

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
(6,095 Views)

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

Message 2 of 9
(6,073 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
(6,063 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".

0 Kudos
Message 4 of 9
(6,054 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
(6,050 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?)

0 Kudos
Message 6 of 9
(6,042 Views)

Anyway, thanks for your replies.

0 Kudos
Message 7 of 9
(6,040 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
(6,019 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
(5,837 Views)