5 167 Python Jon Franklin Python Python Python Python USB USB RS485 C Python DLL Python Python dll Python Python ctypes dll ctypes Python C Linux Windows Python C ctypes dll C dll C 168 159
168 DLL Windows DLL Linux `.so` shared object Python `.pyd` DLL Windows Linux Windows C Python Python Python API DLL Python ctypes DLL C 5-1 API Python 5-1 Python Python Python C Python API 160 5 Python
Python C API 169 Python Python API Python C Python Python API Python.h C Python SWIG http://www.swig.org C SWIG Python C http://www. swig.org/papers/py96/python96.html 5-2 170 5-2 Python Python C API 161
5-2 Python 171 5-1 5-2 5-1 Python #include Python.h C API (Callable Python Python methods) C PyObject PyObject (Method table) Python (Initialization) Python.h C API 162 5 Python
Python API 5-2 Python API PyObject: Python PyMethodDef: NULL Python API : PyArg_ParseTuple(): `arg`,, Py_BuildValue(): Python Py_InitModule(): 172,,, 5-2 5-2 PyMethodDef method_name, C char Python method_function, PyCFunction method_ ags, (bit field) `METH_VARARGSMETH_VARARGS` method_docstring, Python C API 163
bit field METH_VARARGS METH_KEYWORDS Python http:// docs.python.org/c-api/structures.html 5-3 5-3 173 `METH_VARARGS` `METH_KEYWORDS` `METH_NOARGS` PyCFunction `PyObject` `PyObject self by convention ` `PyObject args` PyArg_ParseTuple args Python varname=value METH_KEYWORD `PyObject self` `PyObject args` `PyObject kwargs` `PyObject self` NULL METH_VARARGS PyArg_ParseTuple() static PyObject ex_varargs(pyobject self, PyObject args) int param1; double param2; char param3[80]; PyArg_ParseTuple(args, "ids", &dev_handle, ¶m2, param3); return PyString_FromFormat("Received %d, %f, %s" % (param1, param2, param3)); ¶m3[0] 164 5 Python
METH_KEYWORDS METH_KEYWORDS Python C API PyArg_ParseTupleAnd Keywords() PyArg_ParseTupleAndKeywords() int PyArg_ParseTupleAndKeywords(PyObject arg, PyObject kwdict, char format, char kwlist,...); kwdict Python kwlist null METH_KEYWORDS METH_KEYWORDS PyArg_ParseTupleAndKeywords() static PyObject ex_keywords(pyobject self, PyObject args, PyObject kw) int param1; double param2; char param3[80]; static char kwlist[] = "param1", "param2", "param3", NULL 174 if (!PyArg_ParseTupleAndKeywords(args, kw, "ids", kwlist, &dev_handle, ¶m2, param3); return NULL; return PyString_FromFormat("Received %d, %f, %s" % (param1, param2, param3)); METH_NOARGS METH_NOARGS args static PyObject ex_keywords(pyobject self, PyObject noargs) return PyString_FromFormat("No arguments received or expected"); Python PyArg_ParseTuple() PyArg_ParseTupleAndKeywords() Py_BuildValue() Python PyArg_VaParse() PyArg_Parse() PyArg_UnpackTuple() Py_VaBuildValue() Python C API 165
Python C API PyArg_ParseTuple() PyArg_ParseTupleAndKeywords() 5-4 5-4 PyArg_ParseTuple 175 Python C b integer char Python byte c char Python 1 C char d oat double Python C double D complex Py_complex Python Py_complex f oat oat Python C oat h integer short int Python C short int i integer int Python C int l integer long int Python C long int s string char None null s# string `char,int` z string `char ` None None None NULL z# string `char,int` s# None null bytes None static PyObject WriteAnalog(PyObject self, PyObject args) int dev_handle; int out_port; oat out_value; PyArg_ParseTuple(args, "iif", &dev_handle, &out_port, &out_pin, &out_value); rc = AIOWriteData(dev_handle, out_port, out_pin, out_value); return Py_BuildValue("i", rc); AIOWriteData() DLL I/O (+/- V) 166 5 Python
Python C API Python API I/O API I/O C DLL PCI DLL API DLL PDev.h / PDev.h - API for a simple discrete digital I/O card / typedef int dev_handle; #de ne PDEV_OK 1 #de ne PDEV_ERR 0 176 / Open Device Channel Opens a channel to a particular I/O device. The device is speci ed by passing its unit number, which is assigned to the device by a setup utility. dev_handle is an int type. Returns: If dev_handle is > 0 then handle is valid If dev_handle is = 0 then an error has occurred / dev_handle PDevOpen(int unit_num); / Close Device Channel Closes a channel to a particular I/O device. Once a channel is closed it must be explicitly re-opened by using the PDevOpen API function. Closing a channel does not reset the DIO con guration. Returns: If return is 1 (true) then channel closed OK If return is = 0 then an error has occurred / int PDevClose(dev_handle handle); / Reset Device Con guration Forces the device to perform an internal reset. All con guration is returned to the factory default setting (All DIO is de ned as inputs). Python C API 167
Returns: 1 (true) if no error occurred 0 (false) if error encountered / int PDevCfgReset(dev_handle handle); / Con gure Device Discrete I/O De nes the pins to be assigned as outputs. By default all pins are in the read mode initially, and they must be speci cally set to the write mode. All 16 I/O pins are assigned at once. For any pin where the corresponding binary value of the assignment parameter is 1, then the pin will be an output. Returns: 1 (true) if no error occurred 0 (false) if error encountered / int PDevDIOCfg(dev_handle handle, int out_pins); 177 / Read Discrete Input Pin Reads the data present on a particular pin. The pin may be either an input or an output. If the pin is an output the value returned will be the value last assigned to the pin. Returns: The input value for the speci ed pin, which will be either 0 or 1. An error is indicated by a return value of 1. / int PDevDIOReadBit(dev_handle handle, int port, int pin); / Read Discrete Input Port Reads the data present on an entire port and returns it as a byte value. The individual pins may be either inputs or outputs. If the pins have been de ned as inputs then the value read will be the value last assigned to the pins. Returns: An integer value representing the input states of all pins in the speci ed port. Only the least signi cant byte of the return value is valid. An error is indicated by a return value of 1. / int PDevDIOReadPort(dev_handle handle, int port); 168 5 Python
/ Write Discrete Output Pin Sets a particular pin of a speci ed port to a value of either 0 (off) or 1 (on, typically +5V). The pin must be de ned as an output or the call will return an error code. Returns: 1 (true) if no error occurred 0 (false) if error encountered / int PDevDIOWriteBit(dev_handle handle, int port, int pin, int value); / Write Discrete Output Port Sets all of the pins of a speci ed port to the unsigned value passed in port_value parameter. Only the lower eight bits of the parameter are used. If any pin in the port is con gured as an input then an error code will be returned. Returns: 1 (true) if no error occurred 0 (false) if error encountered / int PDevDIOWritePort(dev_handle handle, int port, int value); 8 pin pin 8 DLL 178 #include #include #include <Python.h> <stdio.h> <PDev.h> DLL.pyd Python static PyMethodDef PDevapiMethods[] = "OpenDevice", OpenDev, METH_VARARGS, "Open speci c DIO device.", Python C API 169
; "CloseDevice", CloseDev, METH_VARARGS, "Close an open DIO device.", "Con goutputs", Con gdev, METH_VARARGS, "Con g DIO pins as outputs.", "Con greset", Con grst, METH_VARARGS, "Reset all DIO pins to input mode.", "ReadInputPin", ReadPin, METH_VARARGS, "Read a single speci c pin.", "ReadInputPort", ReadPort, METH_VARARGS, "Read an entire 8-bit port.", "WriteOutputPin", WritePin, METH_VARARGS, "Write to a speci c pin.", "WriteOutputPort", WritePort, METH_VARARGS, "Write to an entire port.", NULL, NULL // / initpdevapi Initialize this module when loaded by Python. Instantiates the methods table. No input parameters. Returns nothing. / void initpdevapi(void) Py_InitModule("PDevapi", PDevapiMethods); dev_handle = 1; 179 API Python IO handle PDevAPI.c #include #include #include <Python.h> <stdio.h> <PDev.h> static PyObject OpenDev(PyObject self, PyObject args) int dev_num; int dev_handle; PyArg_ParseTuple(args, "i", &dev_num); dev_handle = PDevOpen(dev_num); 170 5 Python
return Py_BuildValue("i", dev_handle); static PyObject CloseDev(PyObject self, PyObject args) int dev_handle; int rc; PyArg_ParseTuple(args, "i", &dev_handle); rc = PDevClose(dev_handle); return Py_BuildValue("i", rc); static PyObject Con gdev(pyobject self, PyObject args) int dev_handle; char cfg_str[32]; int rc; memset((char ) cfg_str, '\0', 32); / clear con g string / PyArg_ParseTuple(args, "is", &dev_handle, cfg_str); rc = PDevDIOCfg(dev_handle, cfg_str); return Py_BuildValue("i", rc); static PyObject Con grst(pyobject self, PyObject args) int dev_handle; int rc; PyArg_ParseTuple(args, "i", &dev_handle); rc = PDevCfgReset(dev_handle); return Py_BuildValue("i", rc); 180 static PyObject ReadPin(PyObject self, PyObject args) int dev_handle; int in_port; int in_pin; int in_value; PyArg_ParseTuple(args, "iii", &dev_handle, &in_port, &in_pin); in_value = PDevDIOReadBit(dev_handle, in_port, in_pin); return Py_BuildValue("i", in_value); Python C API 171
static PyObject ReadPort(PyObject self, PyObject args) int dev_handle; int in_port; int in_value; PyArg_ParseTuple(args, "iii", &dev_handle, &in_port); in_value = PDevDIOReadPort(dev_handle, in_port); return Py_BuildValue("i", in_value); static PyObject WritePin(PyObject self, PyObject args) int dev_handle; int out_port; int out_pin; int out_value; PyArg_ParseTuple(args, "iii", &dev_handle, &out_port, &out_pin, &out_value); rc = PDevDIOWriteBit(dev_handle, out_port, out_pin, out_value); return Py_BuildValue("i", rc); static PyObject WritePort(PyObject self, PyObject args) int dev_handle; int out_port; int out_value; PyArg_ParseTuple(args, "iii", &dev_handle, &out_port, &out_value); rc = PDevDIOWritePort(dev_handle, out_port, out_value); return Py_BuildValue("i", rc); 181 static PyMethodDef PDevapiMethods[] = "OpenDevice", OpenDev, METH_VARARGS, "Open speci c DIO device.", "CloseDevice", CloseDev, METH_VARARGS, "Close an open DIO device.", "Con goutputs", Con gdev, METH_VARARGS, "Con g DIO pins as outputs.", "Con greset", Con grst, METH_VARARGS, "Reset all DIO pins to input mode.", "ReadInputPin", ReadPin, METH_VARARGS, "Read a single speci c pin.", "ReadInputPort", ReadPort, METH_VARARGS, 172 5 Python
; "Read an entire 8-bit port.", "WriteOutputPin", WritePin, METH_VARARGS, "Write to a speci c pin.", "WriteOutputPort", WritePort, METH_VARARGS, "Write to an entire port.", NULL, NULL // / initpdevapi Initialize this module when loaded by Python. Instantiates the methods table. No input parameters. Returns nothing. / void initpdevapi(void) Py_InitModule("PDevapi", PDevapiMethods); API API Python Python API handle pin 8bit pin true/false import PDevAPI PDdevID = 1 PDev = 0 182 # open device, check for error return PDev_handle = PDevAPI.OpenDevice(PDevID) if PDev_handle: # de ne port 0 as inputs, port 1 as outputs PDevAPI.Con goutputs(pdev_handle, 0xFF00) pinval = PDevAPI.ReadInputPin(PDev_handle, 0, 2) Python C API 173
if pinval: portval = 49 else: portval = 0 PDevAPI.WriteOutputPort(PDev_handle, 1, 42) PDevAPI.CloseDevice(PDev_handle) return 1 else: print "Could not open device: %d" % PdevID return 0 handle Python True 0 Python False PDev.ConfigOutputs 0xFF00 16 8 0xFF0016 = 11111111000000002 handle I/O true 42 0 42 42 00101010 183 ConfigOutputs() ReadInputPin() WriteOutputPort() CloseDevice() byte - - read-modify-write 174 5 Python
def SetPortBit(PDev_handle, portnum, bitpos): # read the current port state portval = PDevAPI.ReadInputPort(PDev_handle, portnum) if portval >= 0: insval = 1 << bitpos # change the designated bit newval = portval insval # write it back out rc = PDevAPI.WriteOutputPort(PDev_handle, portnum, newval) else: rc = 0 return rc 2 2(0) 1,2(4) 16 mask I/O pin 1 0 portval 1 1,0 0 Python 0 1 def ClearPortBit(PDev_handle, bitpos): # read the current port state portval = PDevAPI.ReadInputPort(PDev_handle, portnum) if portval >= 0: insval = 1 << bitpos newval = ~insval & portval rc = PDevAPI.WriteOutputPort(PDev_handle, portnum, newval) else: rc = 0 return rc ClearPortBit() Python AND bitpos 2 insval 4 2(2) 1 00000100 11111011 251 portval AND 1 1 0 0 2(2) 0 184 I/O Python C API 175
I/O pin 1 1 I/O C Python Python I/O Python C Python 5-3 5-3 DLL 176 5 Python
Python ctypes DLL ctypes Python DLL ctypes ctypes Python DLL C ctypes 2.5 Linux Windows ctypes DLL ctypes cdll windll oledll cdll Linux Windows cdecl windll Windows stdcall oledll stdcall HRESULT cdecl C Linux Windows ctypes Windows C msvcrt Microsoft Visual C Run-Time ctypes 185 >>> >>> >>> <CDLL 'msvcrt', handle 78000000 at 97b0f0> >>> Testing... 11 >>> Testing... printf() printf() printf() printf() console rc 186 Linux libc = cdll.loadlibrary("libc.so.6") libc = CDLL("libc.so.6") Python ctypes 177
Windows DLL libc = CDLL("msvcrt.dll") Windows.dll Linux DLL ctypes ctypes ctypes DLL ctypes Python C 5-5 ctypes C Python 5-5 ctypes,c,python 187 ctypes C Python c_char char 1 string c_wchar wchar_t 1 unicade string c_ubyte unsigned char int/long c_ushot unsigned short int/long c_uint unsigned int int/long c_long long int/long c_ulong unsigned long int/long c_longlong int64 long long int/long c_ulonglong unsigned int64 long long int/long c_ oat oat oat c_double double oat c_longdouble long double oat c_char_p `char (NULL-terminated)` string None c_wchar_p `wchar_t (NULL-terminated)` unicode None c_void_p void int/long None ctypes Python C Python DLL Python float DLL somedll somefunc() 178 5 Python
int_var = 5 oat_var = 22.47 somedll.somefunc(int_var, oat_var) Python Python ctypes somedll.somefunc(int_var, c_double( oat_var)) Python None, integer, long string ctypes DLL None NULL string integer long C int long C int ctypes ctypes DLL ctypes http://docs.python.org/library/ctypes.html ctypes DLL 12 ctypes Python C structure 14 ctypes USB API 188 Python DLL Python Python DLL API DLL Python Python 14 ctypes 179
Python Python http://docs.python.org/release/2.6.5/ 2.6.5 C C++ Python http://docs.python.org/release/2.6.5/c-api/index.html: Python http://docs.python.org/library/ctypes.html: ctypes 180 5 Python