PyDAQmx icon indicating copy to clipboard operation
PyDAQmx copied to clipboard

Handling functions that return non-zero gracefully

Open sidneycadot opened this issue 11 years ago • 3 comments

Hi Pierre,

I've been toying with PyDAQmx for a bit, thanks for this -- looks like a well-done wrapper.

One thing I bumped into was this:

In C, it is possible to use PyDAQmx.DAQmxGetSysDevNames() with a NULL char* argument to get the number of characters that need to be reserved for the characater buffer. This will return a positive value that does not indicate a warning.

However, PyDAQmx wraps the C functions inside the 'mafunction' wrapper that auto-throws an exception whenever a function returns non-zero. So it is impossible (or at least a bit cumbersome) to use this function in this way.

Is there an easy way around this?

The best I could think of now was to catch the exception and extract the "error", by hand, like this, which seems rather roundabout. In the process, I also need to silence stdout because mafunction() prints a WARNING message when warnings happen.

def GetSysDevNames():

    import sys, io

    # We know that PyDAQmx.DAQmxGetSysDevNames(None, 0)
    # will return a positive value; PyDAQmx intercepts
    # this, prints a warning, then throws a DAQError in response.
    #
    # To work around this, we need to
    #
    #   (1) silence the print()
    #   (2) catch the error

    old_stdout = sys.stdout
    sys.stdout = io.StringIO() # dummy fiel to catch print() output

    try:
        numBytesNeeded = PyDAQmx.DAQmxGetSysDevNames(None, 0)
    except PyDAQmx.DAQError as e:
        numBytesNeeded = e.error

    # Restore stdout
    sys.stdout = old_stdout

    # We now know how many bytes are needed.
    # Allocate the buffer

    stringBuffer = ctypes.create_string_buffer(numBytesNeeded)

    # Get the device names
    PyDAQmx.DAQmxGetSysDevNames(stringBuffer, numBytesNeeded)

    # Extract the device name string
    return ctypes.string_at(stringBuffer)

Is there a simpler/better way to do this? It could be useful to provide a way to call NIDAQmx functions without invoking the automatic translation of nonzero return values to DAQError exceptions.

sidneycadot avatar Apr 09 '14 07:04 sidneycadot

Hi,

I didn't know this feature. It should be possible to change the way error are caught for this function. I post a solution on a new branch (DAQmxGetSysFunction). Can you test it ? (I havn't)

Pierre

Le 09/04/2014 09:03, Sidney Cadot a écrit :

Hi Pierre,

I've been toying with PyDAQmx for a bit, thanks for this -- looks like a well-done wrapper.

One thing I bumped into was this:

In C, it is possible to use PyDAQmx.DAQmxGetSysDevNames() with a NULL char* argument to get the number of characters that need to be reserved for the characater buffer. This will return a positive value that does not indicate a warning.

However, PyDAQmx wraps the C functions inside the 'mafunction' wrapper that auto-throws an exception whenever a function returns non-zero. So it is impossible (or at least a bit cumbersome) to use this function in this way.

Is there an easy way around this?

The best I could think of now was to catch the exception and extract the "error", by hand, like this, which seems rather roundabout. In the process, I also need to silence stdout because mafunction() prints a WARNING message when warnings happen.

|def GetSysDevNames():

 import sys, io

 # We know that PyDAQmx.DAQmxGetSysDevNames(None, 0)
 # will return a positive value; PyDAQmx intercepts
 # this, prints a warning, then throws a DAQError in respose.
 #
 # To work around this, we need to
 #
 #   (1) silence the print()
 #   (2) catch the error

 old_stdout = sys.stdout
 sys.stdout = io.StringIO() # dummy fiel to catch print() output

 try:
     numBytesNeeded = PyDAQmx.DAQmxGetSysDevNames(None, 0)
 except PyDAQmx.DAQError as e:
     numBytesNeeded = e.error

 # Restore stdout
 sys.stdout = old_stdout

 # We now know how many bytes are needed.
 # Allocate the buffer

 stringBuffer = ctypes.create_string_buffer(numBytesNeeded)

 # Get the device names
 PyDAQmx.DAQmxGetSysDevNames(stringBuffer, numBytesNeeded)

 # Extract the device name string
 return ctypes.string_at(stringBuffer)

| |

Is there a simpler/better way to do this? It could be useful to provide a way to call NIDAQmx functions without invoking the automatic translation of nonzero return values to DAQError exceptions.

— Reply to this email directly or view it on GitHub https://github.com/clade/PyDAQmx/issues/11.

clade avatar Apr 09 '14 09:04 clade

I checked out that branch.

What is the proper way of testing it -- should I just do a "python setup.py install" (does that work properly on Python 3.3) ? Or is it possible to test this locally inside that directory?

Unfortunately, I do not fully understand the way Python handles modules.

sidneycadot avatar Apr 10 '14 17:04 sidneycadot

This seems to be fixed as of PyDAQmx 1.3.

apteryks avatar Sep 22 '15 20:09 apteryks