How to produce a Python ctypes instance

1.4k views Asked by At

I am attempting to use the pyueye library to run ML cameras, and am running into problems with ctypes. One function requires an argument of type 'ctypes instance,' and despite trying every possible variation I cannot figure out how to produce this with the ctypes library. There is no documentation for python with this library, but the C documentation of the function I am trying to use is:

Syntax

INT is_SetAutoParameter (HIDS hCam, INT param, double* pval1, double* pval2)

Example 1

//Enable auto gain control:

double dEnable = 1;

int ret = is_SetAutoParameter (hCam, IS_SET_ENABLE_AUTO_GAIN, &dEnable, 0);

The code and subsequent error I am recieving in python is:

nRet = ueye.is_SetAutoParameter(hCam, ueye.IS_SET_ENABLE_AUTO_GAIN, ctypes.byref(ctypes.c_long(1)), ctypes.byref(ctypes.c_long(0)))

Error:
ret = _is_SetAutoParameter(_hCam, _param, ctypes.byref(pval1), ctypes.byref(pval2))
TypeError: byref() argument must be a ctypes instance, not 'CArgObject'

Any advice on ctypes instances? Thanks

EDIT: Minimal reproducible example

from pyueye import ueye
import ctypes

class Turfcam:
    def main(self):
        turfcam.take_photo()

    def take_photo(self):
        hCam = ueye.HIDS(0)
        pval1 = ctypes.c_double(1)
        pval2 = ctypes.c_double(0)
        nRet = ueye.is_SetAutoParameter(hCam, ueye.IS_SET_ENABLE_AUTO_GAIN, ctypes.byref(pval1), ctypes.byref(pval2))

        # Camera Init
        nRet = ueye.is_InitCamera(hCam, None)

if __name__ == "__main__":
    turfcam = Turfcam()
    turfcam.main()
2

There are 2 answers

0
AvD On

To complete the answer given by Mark Tolonen: the following code works OK (but probably you also want to check the error code nRet):

    def take_photo(self):
        hCam = ueye.HIDS(0)
        # Camera Init (you must do this before using hCam !!)
        nRet = ueye.is_InitCamera(hCam, None)
        
        pval1 = ctypes.c_double(1)
        pval2 = ctypes.c_double(0)
        nRet = ueye.is_SetAutoParameter(hCam, ueye.IS_SET_ENABLE_AUTO_GAIN, pval1, pval2)
5
Mark Tolonen On

The pyueye library has some minimal documentation:

_is_SetAutoParameter = _bind("is_SetAutoParameter", [ctypes.c_uint, ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double)], ctypes.c_int)


def is_SetAutoParameter(hCam, param, pval1, pval2):
    """
    :param hCam: c_uint (aka c-type: HIDS)
    :param param: c_int (aka c-type: INT)
    :param pval1: c_double (aka c-type: double \*)
    :param pval2: c_double (aka c-type: double \*)
    :returns: success, or no success, that is the answer
    :raises NotImplementedError: if function could not be loaded
    """
    if _is_SetAutoParameter is None:
        raise NotImplementedError()

    _hCam = _value_cast(hCam, ctypes.c_uint)
    _param = _value_cast(param, ctypes.c_int)

    ret = _is_SetAutoParameter(_hCam, _param, ctypes.byref(pval1), ctypes.byref(pval2))

    return ret

The wrapper is doing the byref, so only a ctypes object needs to be passed. The uEye docs say the parameters can be input or output parameters, so always create c_double objects and initialize them as needed for the function passed. Note that for an output parameter you must assign the object a name so it exists after the call to be queried. Input parameters can get away with passing ctypes.c_double(value) directly to the function, but for consistency I'd always assign names to the objects:

Example:

pval1 = ctypes.c_double()
pval2 = ctypes.c_double() # not used for output on IS_GET_ENABLE_AUTO_GAIN 
nRet = ueye.is_SetAutoParameter(hCam, ueye.IS_GET_ENABLE_AUTO_GAIN, pval1, pval2)
print(pval1.value) # query the returned value