One, C language Run Pyfun Pyobject object
The idea is to provide the arguments in the C language to the Python function:
- Get the PY Function object (pyobject), function parameter (c type)
- Get Gil (pygilstate_ensure)
- Make sure the fun object can be called
- parameter conversion to Python corresponding type (py_buildvalue)
- Calling the Python function (Pyobject_call)
- OK call no exception
- Check the return value
- Release Gil (pygilstate_release)
- Exception handling
#include "Python.h"/* Execute func (x, y) in the Python interpreter. The arguments and return result of the function must be Python floats */double call_func (Pyobject *func, double x, Dou Ble y) {pyobject *args; Pyobject *kwargs; Pyobject *result = 0; Double retval; /* Make sure we own the GIL */pygilstate_state state = Pygilstate_ensure (); /* Verify that Func is a proper callable */* You must first have a Python callable object that represents the call you are going to invoke. This can be a function, class, method, built-in method, or anything else that implements the __call__ () operation. To make sure that it is callable, you can use the Pycallable_check () to do the check */if (!) like the following code. Pycallable_check (func)) {fprintf (stderr, "call_func:expected a callable\n"); Goto fail; }/* Build arguments/* use Py_buildvalue () to construct the parameter tuple or dictionary */args = Py_buildvalue ("(DD)", x, y); Kwargs = NULL; /* Call the function */* use Pyobject_call () to pass a callable object to it, a parameter tuple, and an optional keyword dictionary. If there is no keyword argument, pass NULL */result = Pyobject_call (func, args, Kwargs); /* You need to make sure that py_decref () or py_xdecref () cleanup parameters are used. The second function is relatively safe because it allows you to pass a null pointer (ignoring it directly), which is why we use theIt to clean up the optional keyword parameters. */Py_decref (args); Py_xdecref (Kwargs); /* Check for Python exceptions (if any) */* After calling the Python function, use the pyerr_occurred () function to verify that an exception occurred */if (pyerr_occurred ()) {Pyerr_print (); Goto fail; }/* Verify The result is a float object */if (! Pyfloat_check (Result)) {fprintf (stderr, "call_func:callable didn ' t return a float\n"); Goto fail; }/* Create the return value */retval = pyfloat_asdouble (result); Py_decref (result); /* Restore previous GIL State and return */pygilstate_release (state); return retval;fail:py_xdecref (Result); Pygilstate_release (state); Abort (); Change to something more appropriate}
Note that each PyGILState_Ensure()
call must follow a matching PyGILState_Release()
call--even if an error occurs. Here, we use a goto
statement that looks like a scary design, but we actually use it to transfer control to a normal exit block to perform the corresponding operation. The fail:
code behind the tag is the same as the purpose of the Python fianl:
block.
Second, use module name and method name to get Pyfun Pyobject object
- Get module name string, method name string
- Module name converted to Python string type (pyunicode_fromstring)
- Simulates the Import behavior of Python (pyimport_import), because we want to get the function via Python's logic
- By the Python module Fetch method (pyobject_getattrstring), this API fetch method uses the C string
- Returns the method, when the object type of Python
/* Load a symbol from a module */pyobject *import_name (const char *modname, const char *symbol) { pyobject *u_name, *m Odule; U_name = pyunicode_fromstring (modname); module = Pyimport_import (u_name); Py_decref (u_name); Return pyobject_getattrstring (module, symbol);}
Three, c simulation python run
- Initializing the Python Environment (py_initialize)
- The Import Module acquisition method (see the second part of this article) is Pyobject
- Call Method Pyobject (see the first part of this article)
- End Python Environment (py_finalize)
/* Simple Embedding Example */int main () { pyobject *pow_func; Double X; Py_initialize (); /* Get A reference to the MATH.POW function * /Pow_func = Import_name ("math", "pow"); /* Call it using our Call_func () code */ for (x = 0.0; x < 10.0; x + + 0.1) { printf ("%0.2f%0.2f\n", X, Call_ Func (pow_func,x,2.0)); } /* Done * /Py_decref (pow_func); Py_finalize (); return 0;}
Compile and run,
Gcc-g embed.c-i/home/hellcat/anaconda3/include/python3.6m -l/home/hellcat/anaconda3/lib/python3.6/ Config-3.6m-x86_64-linux-gnu-lpython3.6m
Iv. calling the callable Pyobject in C re-encapsulation
This is a meaningless function, just to show the C API Pyobject essential run logic--pyobject can refer to any Python object, here is an example of its receive function:
/* Extension function for testing the C-python callback */static pyobject *py_call_func (pyobject *self, Pyobject *args) { C1/>pyobject *func; Double x, y, result; if (! Pyarg_parsetuple (args, "Odd", &func,&x,&y)) { return NULL; } result = Call_func (func, x, y); Return Py_buildvalue ("D", result);}
Write it to the pysample.c in the previous section, with the following effect
SampleAdd(x,y):x+y... sample. Call_func(add,3,4)7.0>>>
"Python coolbook" C extension Library _ its six _ calls Python code from the C language