Extended Python module series (3) ---- Parameter Parsing and result encapsulation, python ----

Source: Internet
Author: User

Extended Python module series (3) ---- Parameter Parsing and result encapsulation, python ----

In the previous section, we introduced the overall process of extending the Python built-in modules in C language through a simple example. Starting from this section, we will discuss some details in depth, in the detailed discussion, [reference count] is involved from the beginning. First, we will discuss the Parameter Parsing of Python functions encapsulated in C language and the encapsulation returned by function results.

Parameter Parsing

The most common interface is

int PyArg_ParseTuple(PyObject *arg, char *format, ...);

Arg is a tuple object, which is passed to the C function from python. The format parameter must be a string. Generally, each character represents a type; the remaining parameters are the addresses of the variables corresponding to the format. The return value is an integer, 1 is returned for successful parsing, and 0 is returned for parsing errors.

The Python Object parameter received by the function is borrowed reference, so you do not need to increase the reference count.

Example:

Int OK; int I, j; long k, l; const char * s; int size; OK = PyArg_ParseTuple (args ,""); /* No parameter * // * Python call: f ()*/
OK = PyArg_ParseTuple (args, "s", & s);/* the parameter is a string * // * Possible Python call: f ('whoops! ')*/
OK = PyArg_ParseTuple (args, "lls", & k, & l, & s);/* the parameters are two long integers and one string * // * Possible Python call: f (1, 2, 'three ')*/
{Const char * file; const char * mode = "r"; int bufsize = 0; OK = PyArg_ParseTuple (args, "s | si", & file, & mode, & bufsize);/* The parameter must have at least one character string. It can have another character string or integer * // * Possible Python cballs: f ('spam') f ('spam ', 'W') f ('spam', 'wb', 100000 )*/}
{Int left, top, right, bottom, h, v; OK = PyArg_ParseTuple (args, "(ii)", & left, & top, & right, & bottom, & h, & v);/* the parameter is two tuples. The first tuple has two elements, each tuple is composed of two integers * // * Possible Python call: f (0, 0), (400,300), (10, 10 ))*/}
PyObject * p; OK = PyArg_ParseTuple (args, "O", & p);/* the parameter is a PyObject object that can represent any type in Python */
/* Possible Python call: f (1, 2 ))*/

The common format strings provided in Python C APIs are as follows (not all are listed, and others can be found in Python2.7 ):

S => const char *, convert the Python string to the character pointer; s # => const cahr *, Py_ssize_t, convert the Python string to the character pointer and the character length; B ==> unsigned char. convert a non-negative Python integer to C unsigned char; B ==> unsigned char; convert a Python integer to C unsigned char; h ==> short inH ==> unsigned short inti ==> intI ==> unsigned intl ==> long intk ==> unsigned longL ==> PY_LONG_LONG, convert a Python integer to a long value of C, which may not be supported by some platforms; K => unsigned py_long_logrowth => float: convert a Python floating point number to a float of C. Pyhton only has the double type, so the precision is lost here. D => double: Convert the Python floating point number to the double value of C. There is no loss of precision. O => PyObject *: Save the Python object in PyObject, here, the object reference count will not increase; (items) ==> tuple/* Other characters */| the following parameters are optional. The default values of default parameters must be provided in PyArg_ParseTuple ;: the string parameter list is at: end, followed by a description of the function; followed by an error description to replace the default error message.
Static PyObject * distance (PyObject * self, PyObject * args) {double x0, y0, z0, x1, y1, z1; if (! PyArg_ParseTuple (args, "(ddd)", & x0, & y0, & z0, & x1, & y1, & z1 )) /* accept two tuple parameters */{return NULL;} return PyFloat_FromDouble (sqrt (x0-x1) * (x0-x1) + (y0-y1) * (y0-y1) + (z0-z1) * (z0-z1 )));}

 

Result returned

Which corresponds to the parameter parsing function PyArg_ParseTuple is:

PyObject *Py_BuildValue(char *format, ...);

Format also specifies the type of each parameter in each parameter list, but the parameter passed to this function cannot be a pointer. Here, PyArg_ParseTuple is different and only the value is passed. Another important difference is that Py_BuildValue returns PyObject * and the reference count is automatically 1. If a PyObject * parameter is passed to the function, for example, the following code, in this case, the reference parameter of p will be increamented by one.

PyObject*  p = PyFloat_FromDouble(1.0);Py_BuildValue('O', p);

In Python source code: Py_BuildValue will call static PyObject * do_mkvalue (const char ** p_format, va_list * p_va, int flags). Here the 'O' processing is as follows:

Case 'N': case's ': case 'O': if (** p_format =' & ') {typedef PyObject * (* converter) (void *); converter func = va_arg (* p_va, converter); void * arg = va_arg (* p_va, void *); ++ * p_format; return (* func) (arg );} else {PyObject * v; v = va_arg (* p_va, PyObject *); if (v! = NULL) {if (* p_format-1 )! = 'N') Py_INCREF (v);/* If the format is not 'n', the reference count is increased by 1. If the format is 'n ', reference count unchanged */} else if (! PyErr_Occurred ()/* If a NULL was passed * because a call that shoshould * have constructed a value * failed, that's OK, and we * pass the error on; but if * no error occurred it's not * clear that the caller knew * what she was doing. */PyErr_SetString (PyExc_SystemError, "NULL object passed to Py_BuildValue"); return v ;}

 

Example:

The left side is the function call form, and the right side is the returned Python value:

Py_BuildValue("")                        NonePy_BuildValue("i", 123)                  123Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)Py_BuildValue("s", "hello")              'hello'Py_BuildValue("ss", "hello", "world")    ('hello', 'world')Py_BuildValue("s#", "hello", 4)          'hell'Py_BuildValue("()")                      ()Py_BuildValue("(i)", 123)                (123,)Py_BuildValue("(ii)", 123, 456)          (123, 456)Py_BuildValue("(i,i)", 123, 456)         (123, 456)Py_BuildValue("[i,i]", 123, 456)         [123, 456]Py_BuildValue("{s:i,s:i}",              "abc", 123, "def", 456)    {'abc': 123, 'def': 456}Py_BuildValue("((ii)(ii)) (ii)",              1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))

In addition to using the Py_BuildValue function to return Python objects, you can also call the encapsulated functions provided by each type. For example, in our previous test module, the distance function needs to return a Python float object, you can call the PyFloat_FromDouble provided by floatobject:

PyObject * PyFloat_FromDouble (double fval) {register PyFloatObject * op; if (free_list = NULL) {if (free_list = fill_free_list () = NULL) return NULL ;} /* Inline PyObject_New */op = free_list; free_list = (PyFloatObject *) Py_TYPE (op); (void) PyObject_INIT (op, & PyFloat_Type ); /* initialize reference count */op-> ob_fval = fval; return (PyObject *) op ;}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.