1. Extending Python with C or C++¶
It is quite easy to add new built-in modules to Python, if you know how to program in C. Such extension modules can do two things that can't be done directly in Python: they can implement new built-in object types, and they can call C library functions and system calls.
To support extensions, the Python API (Application Programmers Interface)
defines a set of functions, macros and variables that provide access to most
aspects of the Python run-time system. The Python API is incorporated in a C
source file by including the header "Python.h".
The compilation of an extension module depends on its intended use as well as on your system setup; details are given in later chapters.
泚é
The C extension interface is specific to CPython, and extension modules do
not work on other Python implementations. In many cases, it is possible to
avoid writing C extensions and preserve portability to other implementations.
For example, if your use case is calling C library functions or system calls,
you should consider using the ctypes module or the cffi library rather than writing
custom C code.
These modules let you write Python code to interface with C code and are more
portable between implementations of Python than writing and compiling a C
extension module.
1.1. A Simple Example¶
Let's create an extension module called spam (the favorite food of Monty
Python fans...) and let's say we want to create a Python interface to the C
library function system() [1]. This function takes a null-terminated
character string as argument and returns an integer. We want this function to
be callable from Python as follows:
>>> import spam
>>> status = spam.system("ls -l")
Begin by creating a file spammodule.c. (Historically, if a module is
called spam, the C file containing its implementation is called
spammodule.c; if the module name is very long, like spammify, the
module name can be just spammify.c.)
The first two lines of our file can be:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
which pulls in the Python API (you can add a comment describing the purpose of the module and a copyright notice if you like).
泚é
Since Python may define some pre-processor definitions which affect the standard
headers on some systems, you must include Python.h before any standard
headers are included.
#define PY_SSIZE_T_CLEAN was used to indicate that Py_ssize_t should be
used in some APIs instead of int.
It is not necessary since Python 3.13, but we keep it here for backward compatibility.
See æååãšãããã¡ for a description of this macro.
All user-visible symbols defined by Python.h have a prefix of Py or
PY, except those defined in standard header files.
Tip
For backward compatibility, Python.h includes several standard header files.
C extensions should include the standard headers that they use,
and should not rely on these implicit includes.
If using the limited C API version 3.13 or newer, the implicit includes are:
<assert.h><intrin.h>(on Windows)<inttypes.h><limits.h><math.h><stdarg.h><wchar.h><sys/types.h>(if present)
If Py_LIMITED_API is not defined, or is set to version 3.12 or older,
the headers below are also included:
<ctype.h><unistd.h>(on POSIX)
If Py_LIMITED_API is not defined, or is set to version 3.10 or older,
the headers below are also included:
<errno.h><stdio.h><stdlib.h><string.h>
The next thing we add to our module file is the C function that will be called
when the Python expression spam.system(string) is evaluated (we'll see
shortly how it ends up being called):
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return PyLong_FromLong(sts);
}
There is a straightforward translation from the argument list in Python (for
example, the single expression "ls -l") to the arguments passed to the C
function. The C function always has two arguments, conventionally named self
and args.
The self argument points to the module object for module-level functions; for a method it would point to the object instance.
The args argument will be a pointer to a Python tuple object containing the
arguments. Each item of the tuple corresponds to an argument in the call's
argument list. The arguments are Python objects --- in order to do anything
with them in our C function we have to convert them to C values. The function
PyArg_ParseTuple() in the Python API checks the argument types and
converts them to C values. It uses a template string to determine the required
types of the arguments as well as the types of the C variables into which to
store the converted values. More about this later.
PyArg_ParseTuple() returns true (nonzero) if all arguments have the right
type and its components have been stored in the variables whose addresses are
passed. It returns false (zero) if an invalid argument list was passed. In the
latter case it also raises an appropriate exception so the calling function can
return NULL immediately (as we saw in the example).
1.2. Intermezzo: Errors and Exceptions¶
An important convention throughout the Python interpreter is the following: when
a function fails, it should set an exception condition and return an error value
(usually -1 or a NULL pointer). Exception information is stored in
three members of the interpreter's thread state. These are NULL if
there is no exception. Otherwise they are the C equivalents of the members
of the Python tuple returned by sys.exc_info(). These are the
exception type, exception instance, and a traceback object. It is important
to know about them to understand how errors are passed around.
Python API ã§ã¯ãæ§ã ãªåã®äŸå€ãã»ããããããã®é¢æ°ãããã€ãå®çŸ©ããŠããŸãã
ãã£ãšãããçšããããã®ã¯ PyErr_SetString() ã§ããåŒæ°ã¯äŸå€ãªããžã§ã¯ããš C æååã§ããäŸå€ãªããžã§ã¯ãã¯éåžžã PyExc_ZeroDivisionError ã®ãããªå®çŸ©æžã¿ã®ãªããžã§ã¯ãã§ãã C æååã¯ãšã©ãŒã®åå ã瀺ããPython æååãªããžã§ã¯ãã«å€æãããŠäŸå€ã® "ä»å±å€" ã«ä¿åãããŸãã
ããäžã€æçšãªé¢æ°ãšã㊠PyErr_SetFromErrno() ããããŸãããã®é¢æ°ã¯åŒæ°ã«äŸå€ã ãããšããä»å±å€ã¯ã°ããŒãã«å€æ° errno ããæ§ç¯ããŸãããã£ãšãæ±çšçãªé¢æ°ã¯ PyErr_SetObject() ã§ãäºã€ã®ãªããžã§ã¯ããäŸå€ãšä»å±å€ãåŒæ°ã«ãšããŸããããã颿°ã«æž¡ããªããžã§ã¯ãã«ã¯ Py_INCREF() ã䜿ãå¿
èŠã¯ãããŸããã
äŸå€ãã»ãããããŠãããã©ããã¯ã PyErr_Occurred() ã䜿ã£ãŠéç Žå£çã«èª¿ã¹ãããŸãããã®é¢æ°ã¯çŸåšã®äŸå€ãªããžã§ã¯ããè¿ããŸããäŸå€ãçºçããŠããªãå Žåã«ã¯ NULL ãè¿ããŸããéåžžã¯ã颿°ã®æ»ãå€ãããšã©ãŒãçºçããããå€å¥ã§ããã¯ããªã®ã§ã PyErr_Occurred() ãåŒã³åºãå¿
èŠã¯ãããŸããã
颿° g ãåŒã³åºã f ããåè
ã®é¢æ°ã®åŒã³åºãã«å€±æããããšãæ€åºãããšã f èªäœã¯ãšã©ãŒå€ (倧æµã¯ NULL ã -1) ãè¿ããã°ãªããŸããããããã PyErr_* 颿°çŸ€ã®ãããããåŒã³åºãå¿
èŠã¯ ãããŸãã --- ãªããªãã g ããã§ã«åŒã³åºããŠããããã§ããæ¬¡ãã§ f ãåŒã³åºããã³ãŒãããšã©ãŒã瀺ãå€ã èªããåŒã³åºããã³ãŒã ã«è¿ãããšã«ãªããŸãããåæ§ã« PyErr_* 㯠åŒã³åºããŸãã ã以äžåæ§ã«ç¶ããŸã --- ãšã©ãŒã®æã詳ããåå ã¯ãæåã«ãšã©ãŒãæ€åºãã颿°ããã§ã«å ±åããŠããããã§ãããšã©ãŒã Python ã€ã³ã¿ããªã¿ã®ã¡ã€ã³ã«ãŒãã«å°éãããšãçŸåšå®è¡äžã® Python ã³ãŒãã¯äžæåæ¢ãã Python ããã°ã©ããæå®ããäŸå€ãã³ãã©ãæ¢ãåºãããšããŸãã
(ã¢ãžã¥ãŒã«ã PyErr_* 颿°ãããäžåºŠåŒã³åºããŠããã詳现ãªãšã©ãŒã¡ãã»ãŒãžãæäŸãããããªç¶æ³ããããŸãããã®ãããªç¶æ³ã§ã¯ãããã¹ãã§ãããšã¯ãããäžè¬çãªèŠåãšããŠã¯ããã®é¢æ°ãäœåºŠãåŒã³åºãå¿
èŠã¯ãªãããšãããã°ãšã©ãŒã®åå ã«é¢ããæ
å ±ã倱ãçµæã«ãªããã¡ã§ã: ããã«ãããã»ãšãã©ã®æäœãæ§ã
ãªçç±ãã倱æãããããããŸãã)
ãã颿°åŒã³åºãã§ã®åŠçã®å€±æã«ãã£ãŠã»ãããããäŸå€ãç¡èŠããã«ã¯ã PyErr_Clear() ãåŒã³åºããŠäŸå€ç¶æ
ãæç€ºçã«æ¶å»ããªããŠã¯ãªããŸããããšã©ãŒãã€ã³ã¿ããªã¿ã«ã¯æž¡ããããªããèªåã§ (äœãä»ã®äœæ¥ãè¡ã£ãããäœãèµ·ãããªãã£ããã®ããã«èŠãããããããª) ãšã©ãŒåŠçãå®å
šã«è¡ãå Žåã«ã®ã¿ã PyErr_Clear() ãåŒã³åºãããã«ãã¹ãã§ãã
malloc() ã®åŒã³åºã倱æã¯ãåžžã«äŸå€ã«ããªããŠã¯ãªããŸãã --- malloc() (ãŸã㯠realloc()) ãçŽæ¥åŒã³åºããŠããã³ãŒãã¯ã PyErr_NoMemory() ãåŒã³åºããŠã倱æã瀺ãå€ãè¿ããã°ãªããŸããããªããžã§ã¯ããçæããå
šãŠã®é¢æ° (äŸãã° PyLong_FromLong()) 㯠PyErr_NoMemory() ã®åŒã³åºããæžãŸããŠããŸãã®ã§ããã®èŠåãé¢ä¿ããã®ã¯çŽæ¥ malloc() ãåŒã³åºãã³ãŒãã ãã§ãã
ãŸãã PyArg_ParseTuple() ãšããéèŠãªäŸå€ãé€ããŠãæŽæ°ã®ç¶æ
ã³ãŒããè¿ã颿°ã¯ãããŠããUnix ã®ã·ã¹ãã ã³ãŒã«ãšåãããåŠçãæåããéã«ã¯ãŒããŸãã¯æ£ã®å€ãè¿ãã倱æããå Žåã«ã¯ -1 ãè¿ããŸãã
æåŸã«ããšã©ãŒæšç€ºå€ãè¿ãéã«ã(ãšã©ãŒãçºçãããŸã§ã«æ¢ã«çæããŠããŸã£ããªããžã§ã¯ãã«å¯Ÿã㊠Py_XDECREF() ã Py_DECREF() ãåŒã³åºããŠ) ãã¿åŠçãæ³šææ·±ãè¡ã£ãŠãã ãã!
The choice of which exception to raise is entirely yours. There are predeclared
C objects corresponding to all built-in Python exceptions, such as
PyExc_ZeroDivisionError, which you can use directly. Of course, you
should choose exceptions wisely --- don't use PyExc_TypeError to mean
that a file couldn't be opened (that should probably be PyExc_OSError).
If something's wrong with the argument list, the PyArg_ParseTuple()
function usually raises PyExc_TypeError. If you have an argument whose
value must be in a particular range or must satisfy other conditions,
PyExc_ValueError is appropriate.
You can also define a new exception that is unique to your module. The simplest way to do this is to declare a static global object variable at the beginning of the file:
static PyObject *SpamError = NULL;
and initialize it by calling PyErr_NewException() in the module's
Py_mod_exec function (spam_module_exec()):
SpamError = PyErr_NewException("spam.error", NULL, NULL);
Since SpamError is a global variable, it will be overwritten every time
the module is reinitialized, when the Py_mod_exec function is called.
For now, let's avoid the issue: we will block repeated initialization by raising an
ImportError:
static PyObject *SpamError = NULL;
static int
spam_module_exec(PyObject *m)
{
if (SpamError != NULL) {
PyErr_SetString(PyExc_ImportError,
"cannot initialize spam module more than once");
return -1;
}
SpamError = PyErr_NewException("spam.error", NULL, NULL);
if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot spam_module_slots[] = {
{Py_mod_exec, spam_module_exec},
{0, NULL}
};
static struct PyModuleDef spam_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "spam",
.m_size = 0, // non-negative
.m_slots = spam_module_slots,
};
PyMODINIT_FUNC
PyInit_spam(void)
{
return PyModuleDef_Init(&spam_module);
}
Note that the Python name for the exception object is spam.error. The
PyErr_NewException() function may create a class with the base class
being Exception (unless another class is passed in instead of NULL),
described in çµã¿èŸŒã¿äŸå€.
Note also that the SpamError variable retains a reference to the newly
created exception class; this is intentional! Since the exception could be
removed from the module by external code, an owned reference to the class is
needed to ensure that it will not be discarded, causing SpamError to
become a dangling pointer. Should it become a dangling pointer, C code which
raises the exception could cause a core dump or other unintended side effects.
For now, the Py_DECREF() call to remove this reference is missing.
Even when the Python interpreter shuts down, the global SpamError
variable will not be garbage-collected. It will "leak".
We did, however, ensure that this will happen at most once per process.
We discuss the use of PyMODINIT_FUNC as a function return type later in this
sample.
The spam.error exception can be raised in your extension module using a
call to PyErr_SetString() as shown below:
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
if (sts < 0) {
PyErr_SetString(SpamError, "System command failed");
return NULL;
}
return PyLong_FromLong(sts);
}
1.3. Back to the Example¶
Going back to our example function, you should now be able to understand this statement:
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
It returns NULL (the error indicator for functions returning object pointers)
if an error is detected in the argument list, relying on the exception set by
PyArg_ParseTuple(). Otherwise the string value of the argument has been
copied to the local variable command. This is a pointer assignment and
you are not supposed to modify the string to which it points (so in Standard C,
the variable command should properly be declared as const char
*command).
The next statement is a call to the Unix function system(), passing it
the string we just got from PyArg_ParseTuple():
sts = system(command);
Our spam.system() function must return the value of sts as a
Python object. This is done using the function PyLong_FromLong().
return PyLong_FromLong(sts);
In this case, it will return an integer object. (Yes, even integers are objects on the heap in Python!)
If you have a C function that returns no useful argument (a function returning
void), the corresponding Python function must return None. You
need this idiom to do so (which is implemented by the Py_RETURN_NONE
macro):
Py_INCREF(Py_None);
return Py_None;
Py_None is the C name for the special Python object None. It is a
genuine Python object rather than a NULL pointer, which means "error" in most
contexts, as we have seen.
1.4. The Module's Method Table and Initialization Function¶
I promised to show how spam_system() is called from Python programs.
First, we need to list its name and address in a "method table":
static PyMethodDef spam_methods[] = {
...
{"system", spam_system, METH_VARARGS,
"Execute a shell command."},
...
{NULL, NULL, 0, NULL} /* Sentinel */
};
Note the third entry (METH_VARARGS). This is a flag telling the interpreter
the calling convention to be used for the C function. It should normally always
be METH_VARARGS or METH_VARARGS | METH_KEYWORDS; a value of 0 means
that an obsolete variant of PyArg_ParseTuple() is used.
When using only METH_VARARGS, the function should expect the Python-level
parameters to be passed in as a tuple acceptable for parsing via
PyArg_ParseTuple(); more information on this function is provided below.
The METH_KEYWORDS bit may be set in the third field if keyword
arguments should be passed to the function. In this case, the C function should
accept a third PyObject * parameter which will be a dictionary of keywords.
Use PyArg_ParseTupleAndKeywords() to parse the arguments to such a
function.
The method table must be referenced in the module definition structure:
static struct PyModuleDef spam_module = {
...
.m_methods = spam_methods,
...
};
This structure, in turn, must be passed to the interpreter in the module's
initialization function. The initialization function must be named
PyInit_name(), where name is the name of the module, and should be the
only non-static item defined in the module file:
PyMODINIT_FUNC
PyInit_spam(void)
{
return PyModuleDef_Init(&spam_module);
}
Note that PyMODINIT_FUNC declares the function as PyObject * return type,
declares any special linkage declarations required by the platform, and for C++
declares the function as extern "C".
PyInit_spam() is called when each interpreter imports its module
spam for the first time. (See below for comments about embedding Python.)
A pointer to the module definition must be returned via PyModuleDef_Init(),
so that the import machinery can create the module and store it in sys.modules.
When embedding Python, the PyInit_spam() function is not called
automatically unless there's an entry in the PyImport_Inittab table.
To add the module to the initialization table, use PyImport_AppendInittab(),
optionally followed by an import of the module:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
/* Add a built-in module, before Py_Initialize */
if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
fprintf(stderr, "Error: could not extend in-built modules table\n");
exit(1);
}
/* Pass argv[0] to the Python interpreter */
status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
if (PyStatus_Exception(status)) {
goto exception;
}
/* Initialize the Python interpreter. Required.
If this step fails, it will be a fatal error. */
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyConfig_Clear(&config);
/* Optionally import the module; alternatively,
import can be deferred until the embedded script
imports it. */
PyObject *pmodule = PyImport_ImportModule("spam");
if (!pmodule) {
PyErr_Print();
fprintf(stderr, "Error: could not import module 'spam'\n");
}
// ... use Python C API here ...
return 0;
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
泚é
If you declare a global variable or a local static one, the module may
experience unintended side-effects on re-initialisation, for example when
removing entries from sys.modules or importing compiled modules into
multiple interpreters within a process
(or following a fork() without an intervening exec()).
If module state is not yet fully isolated,
authors should consider marking the module as having no support for subinterpreters
(via Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED).
A more substantial example module is included in the Python source distribution
as Modules/xxlimited.c. This file may be used as a template or simply
read as an example.
1.5. Compilation and Linkage¶
There are two more things to do before you can use your new extension: compiling and linking it with the Python system. If you use dynamic loading, the details may depend on the style of dynamic loading your system uses; see the chapters about building extension modules (chapter C ããã³ C++ æ¡åŒµã®ãã«ã) and additional information that pertains only to building on Windows (chapter Windows äžã§ã® C ããã³ C++ æ¡åŒµã¢ãžã¥ãŒã«ã®ãã«ã) for more information about this.
If you can't use dynamic loading, or if you want to make your module a permanent
part of the Python interpreter, you will have to change the configuration setup
and rebuild the interpreter. Luckily, this is very simple on Unix: just place
your file (spammodule.c for example) in the Modules/ directory
of an unpacked source distribution, add a line to the file
Modules/Setup.local describing your file:
spam spammodule.o
ã远å ããŠããããã¬ãã«ã®ãã£ã¬ã¯ããªã§ make ãå®è¡ããŠãã€ã³ã¿ããªã¿ãåãã«ãããã ãã§ãã Modules/ ãµããã£ã¬ã¯ããªã§ã make ãå®è¡ã§ããŸãããåãã£ãŠ 'make Makefile' ãå®è¡ã㊠Makefile ãåãã«ãããŠãããªããã°ãªãããŸããã(ãã®äœæ¥ã¯ Setup ãã¡ã€ã«ã倿Žãããã³ã«å¿
èŠã§ãã)
ã¢ãžã¥ãŒã«ãå¥ã®ã©ã€ãã©ãªãšãªã³ã¯ãããŠããå¿ èŠãããå Žåãã©ã€ãã©ãªãèšå®ãã¡ã€ã«ã«åæã§ããŸããäŸãã°ä»¥äžã®ããã«ããŸãã
spam spammodule.o -lX11
1.6. C ãã Python 颿°ãåŒã³åºã¶
So far we have concentrated on making C functions callable from Python. The reverse is also useful: calling Python functions from C. This is especially the case for libraries that support so-called "callback" functions. If a C interface makes use of callbacks, the equivalent Python often needs to provide a callback mechanism to the Python programmer; the implementation will require calling the Python callback functions from a C callback. Other uses are also imaginable.
Fortunately, the Python interpreter is easily called recursively, and there is a standard interface to call a Python function. (If you're interested in how to call the Python parser with a particular string as input, see è¶ é«æ°Žæºã¬ã€ã€.)
Python 颿°ã®åŒã³åºãã¯ç°¡åã§ãããŸããC ã®ã³ãŒãã«å¯ŸããŠã³ãŒã«ããã¯ãç»é²ããããšãã Python ããã°ã©ã ã¯ãäœããã®æ¹æ³ã§ Python ã®é¢æ°ãªããžã§ã¯ããæž¡ããã°ãªããŸããããã®ããã«ãã³ãŒã«ããã¯ç»é²é¢æ° (ãŸãã¯ãã®ä»ã®ã€ã³ã¿ãŒãã§ãŒã¹) ãæäŸããã°ãªããŸããããã®ã³ãŒã«ããã¯ç»é²é¢æ°ãåŒã³åºãããéã«ãåŒãæž¡ããã Python 颿°ãªããžã§ã¯ããžã®ãã€ã³ã¿ãã°ããŒãã«å€æ°ã« --- ãããã¯ãã©ããé©åãªå Žæã« --- ä¿åããŸã (颿°ãªããžã§ã¯ãã Py_INCREF() ããããããæ³šæããŠãã ãã!)ãäŸãã°ã以äžã®ãããªé¢æ°ãã¢ãžã¥ãŒã«ã®äžéšã«ãªã£ãŠããããšã§ããã:
static PyObject *my_callback = NULL;
static PyObject *
my_set_callback(PyObject *dummy, PyObject *args)
{
PyObject *result = NULL;
PyObject *temp;
if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}
Py_XINCREF(temp); /* Add a reference to new callback */
Py_XDECREF(my_callback); /* Dispose of previous callback */
my_callback = temp; /* Remember new callback */
/* Boilerplate to return "None" */
Py_INCREF(Py_None);
result = Py_None;
}
return result;
}
This function must be registered with the interpreter using the
METH_VARARGS flag; this is described in section The Module's Method Table and Initialization Function. The
PyArg_ParseTuple() function and its arguments are documented in section
æ¡åŒµã¢ãžã¥ãŒã«é¢æ°ã§ã®ãã©ã¡ã¿å±é.
Py_XINCREF() ããã³ Py_XDECREF() ã¯ããªããžã§ã¯ãã«å¯Ÿããåç
§ã«ãŠã³ããã€ã³ã¯ãªã¡ã³ã/ãã¯ãªã¡ã³ãããããã®ãã¯ãã§ã NULL ãã€ã³ã¿ãæž¡ãããŠãå®å
šã«æäœã§ãã圢åŒã§ã (ãšã¯ãããäžã®æµãã§ã¯ temp ã NULL ã«ãªãããšã¯ãããŸãã)ããããã®ãã¯ããšåç
§ã«ãŠã³ãã«ã€ããŠã¯ã åç
§ã«ãŠã³ãæ³ ã§èª¬æããŠããŸãã
ãã®åŸãã³ãŒã«ããã¯é¢æ°ãåŒã³åºãæãæ¥ãããC 颿° PyObject_CallObject() ãåŒã³åºããŸãããã®é¢æ°ã«ã¯äºã€ã®åŒæ°: Python 颿°ãš Python 颿°ã®åŒæ°ãªã¹ãããããããããä»»æã® Python ãªããžã§ã¯ãã衚ããã€ã³ã¿åã§ããåŒæ°ãªã¹ãã¯åžžã«ã¿ãã«ãªããžã§ã¯ãã§ãªããã°ãªããããã®é·ãã¯åŒæ°ã®æ°ã«ãªããŸããPython 颿°ãåŒæ°ãªãã§åŒã³åºãã®ãªãã NULL ã空ã®ã¿ãã«ãæž¡ããŸã; åäžã®åŒæ°ã§é¢æ°ãåŒã³åºãã®ãªããåèŠçŽ (singleton) ã®ã¿ãã«ãæž¡ããŸãã Py_BuildValue() ã®æžåŒæååäžã«ããŒãåãŸãã¯äžå以äžã®æžåŒåã³ãŒããå
¥ã£ãäžžæ¬åŒ§ãããå Žåããã®é¢æ°ã¯ã¿ãã«ãè¿ããŸãã以äžã«äŸã瀺ããŸã:
int arg;
PyObject *arglist;
PyObject *result;
...
arg = 123;
...
/* Time to call the callback */
arglist = Py_BuildValue("(i)", arg);
result = PyObject_CallObject(my_callback, arglist);
Py_DECREF(arglist);
PyObject_CallObject() 㯠Python ãªããžã§ã¯ããžã®ãã€ã³ã¿ãè¿ããŸã: ãã㯠Python 颿°ããã®æ»ãå€ã«ãªããŸãã PyObject_CallObject() ã¯ãåŒæ°ã«å¯Ÿã㊠"åç
§ã«ãŠã³ãäžç« (reference-count- neutral)" ã§ããäžã®äŸã§ã¯ã¿ãã«ãçæããŠåŒæ°ãªã¹ããšããŠæäŸããŠããããã®ã¿ãã«ã¯ PyObject_CallObject() ã®åŒã³åºãçŽåŸã« Py_DECREF() ãããŠããŸãã
PyObject_CallObject() ã¯æ»ãå€ãšã㊠"æ°ãã" ãªããžã§ã¯ã: æ°èŠã«äœæããããªããžã§ã¯ãããæ¢åã®ãªããžã§ã¯ãã®åç
§ã«ãŠã³ããã€ã³ã¯ãªã¡ã³ããããã®ãè¿ããŸããåŸã£ãŠããã®ãªããžã§ã¯ããã°ããŒãã«å€æ°ã«ä¿åãããã®ã§ãªãããããããšããã®æ»ãå€ã«èå³ããªããŠã (ããããããã§ããã°ãªããã!) äœãããã®æ¹æ³ã§æ»ãå€ãªããžã§ã¯ãã Py_DECREF() ããªããã°ãªããŸããã
ãšã¯ãããæ»ãå€ã Py_DECREF() ããåã«ã¯ãå€ã NULL ã§ãªãããã§ãã¯ããŠããããšãéèŠã§ãããã NULL ãªããåŒã³åºãã Python 颿°ã¯äŸå€ãéåºããŠçµäºãããããŠããŸãã PyObject_CallObject() ãåŒã³åºããŠããã³ãŒãèªäœããŸã Python ããåŒã³åºãããŠããã®ã§ããã°ãä»åºŠã¯ C ã³ãŒããèªåãåŒã³åºããŠãã Python ã³ãŒãã«ãšã©ãŒæšç€ºå€ãè¿ããã°ãªããŸãããããã«ãããã€ã³ã¿ããªã¿ã¯ã¹ã¿ãã¯ãã¬ãŒã¹ãåºåããããäŸå€ãåŠçããããã® Python ã³ãŒããåŒã³åºãããã§ããŸããäŸå€ã®éåºãäžå¯èœã ã£ãããããããªãã®ãªãã PyErr_Clear() ãåŒãã§äŸå€ãæ¶å»ããŠãããã°ãªããŸãããäŸãã°ä»¥äžã®ããã«ããŸã:
if (result == NULL)
return NULL; /* Pass error back */
...use result...
Py_DECREF(result);
Python ã³ãŒã«ããã¯é¢æ°ãã©ããªã€ã³ã¿ãŒãã§ãŒã¹ã«ããããã«ãã£ãŠã¯ãåŒæ°ãªã¹ãã PyObject_CallObject() ã«äžããªããã°ãªããªãå ŽåããããŸããããã±ãŒã¹ã§ã¯ãã³ãŒã«ããã¯é¢æ°ãæå®ããã®ãšåãã€ã³ã¿ãŒãã§ãŒã¹ãä»ããŠãåŒæ°ãªã¹ããæž¡ãããŠãããããããŸããããŸãå¥ã®ã±ãŒã¹ã§ã¯ãæ°ããã¿ãã«ãæ§ç¯ããŠåŒæ°ãªã¹ããæž¡ããã°ãªããªããããããŸããããã®å Žåæãç°¡åãªã®ã¯ Py_BuildValue() ãåŒã¶ããæ¹ã§ããäŸãã°ãæŽæ°ã®ã€ãã³ãã³ãŒããæž¡ããããã°ã以äžã®ãããªã³ãŒãã䜿ãããšã«ãªãã§ããã:
PyObject *arglist;
...
arglist = Py_BuildValue("(l)", eventcode);
result = PyObject_CallObject(my_callback, arglist);
Py_DECREF(arglist);
if (result == NULL)
return NULL; /* Pass error back */
/* Here maybe use the result */
Py_DECREF(result);
Py_DECREF(arglist) ãåŒã³åºãã®çŽåŸããšã©ãŒãã§ãã¯ãããåã«çœ®ãããŠããããšã«æ³šæããŠãã ãã! ãŸããå³å¯ã«èšãã°ããã®ã³ãŒãã¯å®å
šã§ã¯ãããŸãã: Py_BuildValue() ã¯ã¡ã¢ãªäžè¶³ã«ãã¡ãããããããããã§ãã¯ããŠããã¹ãã§ãã
éåžžã®åŒæ°ãšããŒã¯ãŒãåŒæ°ããµããŒããã PyObject_Call() ã䜿ã£ãŠãããŒã¯ãŒãåŒæ°ã䌎ã颿°åŒã³åºããããããšãã§ããŸããäžã®äŸãšåãããã«ã Py_BuildValue() ãäœã£ãŠèŸæžãäœããŸãã
PyObject *dict;
...
dict = Py_BuildValue("{s:i}", "name", val);
result = PyObject_Call(my_callback, NULL, dict);
Py_DECREF(dict);
if (result == NULL)
return NULL; /* Pass error back */
/* Here maybe use the result */
Py_DECREF(result);
1.7. æ¡åŒµã¢ãžã¥ãŒã«é¢æ°ã§ã®ãã©ã¡ã¿å±é¶
The PyArg_ParseTuple() function is declared as follows:
int PyArg_ParseTuple(PyObject *arg, const char *format, ...);
åŒæ° arg 㯠C 颿°ãã Python ã«æž¡ãããåŒæ°ãªã¹ããå ¥ã£ãã¿ãã«ãªããžã§ã¯ãã§ãªããã°ãªããŸããã format åŒæ°ã¯æžåŒæååã§ã Python/C API ãªãã¡ã¬ã³ã¹ããã¥ã¢ã«ã® åŒæ°ã®è§£éãšå€ã®æ§ç¯ ã§è§£èª¬ãããŠããæžæ³ã«åŸããã°ãªããŸãããæ®ãã®åŒæ°ã¯ãããããã®å€æ°ã®ã¢ãã¬ã¹ã§ãæžåŒåæååããæ±ºãŸãåã«ãªã£ãŠããªããã°ãªããŸããã
PyArg_ParseTuple() 㯠Python åŽããäžããããåŒæ°ãå¿
èŠãªåã«ãªã£ãŠããã調ã¹ãã®ã«å¯Ÿãã PyArg_ParseTuple() ã¯åŒã³åºãã®éã«æž¡ããã C 倿°ã®ã¢ãã¬ã¹ãæå¹ãªå€ãæã€ã調ã¹ãããªãããšã«æ³šæããŠãã ãã: ããã§ééããç¯ããšãã³ãŒããã¯ã©ãã·ã¥ãããããããŸããããå°ãªããšãã§ããããªããããã¡ã¢ãªã«äžæžãããŠããŸããŸããæ
éã«!
åŒã³åºãåŽã«æäŸããããªããžã§ã¯ããžã®åç §ã¯ãã¹ãŠ åçš åç § (borrowed reference) ã«ãªããŸã; ãããã®ãªããžã§ã¯ãã®åç §ã«ãŠã³ãããã¯ãªã¡ã³ãããŠã¯ãªããŸãã!
以äžã«ããã€ãã®åŒã³åºãäŸã瀺ããŸã:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int ok;
int i, j;
long k, l;
const char *s;
Py_ssize_t size;
ok = PyArg_ParseTuple(args, ""); /* No arguments */
/* Python call: f() */
ok = PyArg_ParseTuple(args, "s", &s); /* A string */
/* Possible Python call: f('whoops!') */
ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* Two longs and a string */
/* Possible Python call: f(1, 2, 'three') */
ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
/* A pair of ints and a string, whose size is also returned */
/* 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);
/* A string, and optionally another string and an integer */
/* Possible Python calls:
f('spam')
f('spam', 'w')
f('spam', 'wb', 100000) */
}
{
int left, top, right, bottom, h, v;
ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
&left, &top, &right, &bottom, &h, &v);
/* A rectangle and a point */
/* Possible Python call:
f(((0, 0), (400, 300)), (10, 10)) */
}
{
Py_complex c;
ok = PyArg_ParseTuple(args, "D:myfunction", &c);
/* a complex, also providing a function name for errors */
/* Possible Python call: myfunction(1+2j) */
}
1.8. æ¡åŒµã¢ãžã¥ãŒã«é¢æ°ã®ããŒã¯ãŒããã©ã¡ã¿Â¶
PyArg_ParseTupleAndKeywords() ã¯ã以äžã®ããã«å®£èšãããŠããŸã:
int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
const char *format, char * const *kwlist, ...);
arg ãš format ãã©ã¡ã¿ã¯ PyArg_ParseTuple() ã®ãã®ãšåãã§ãã kwdict ãã©ã¡ã¿ã¯ããŒã¯ãŒãåŒæ°ã®å
¥ã£ãèŸæžã§ã Python ã©ã³ã¿ã€ã ã·ã¹ãã ãã第äžãã©ã¡ã¿ãšããŠåãåããŸãã kwlist ãã©ã¡ã¿ã¯åãã©ã¡ã¿ãèå¥ããããã®æååãããªãã NULL çµç«¯ããããªã¹ãã§ã; åãã©ã¡ã¿å㯠format äžã®åæ
å ±ã«å¯ŸããŠå·Šããå³ã®é ã«ç
§åãããŸããæåãããš PyArg_ParseTupleAndKeywords() ã¯çãè¿ãããã以å€ã®å Žåã«ã¯é©åãªäŸå€ãéåºããŠåœãè¿ããŸãã
泚é
ããŒã¯ãŒãåŒæ°ã䜿ã£ãŠããå Žåãã¿ãã«ã¯å
¥ãåã«ããŠäœ¿ããŸãã! kwlist å
ã«ååšããªãããŒã¯ãŒããã©ã¡ã¿ãæž¡ãããå Žåã TypeError ã®éåºãåŒãèµ·ãããŸãã
以äžã«ããŒã¯ãŒãã䜿ã£ãã¢ãžã¥ãŒã«äŸã瀺ããŸãããã㯠Geoff Philbrick (philbrick@hks.com) ã«ããããã°ã©ã äŸãããšã«ããŠããŸã:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
static PyObject *
keywdarg_parrot(PyObject *self, PyObject *args, PyObject *keywds)
{
int voltage;
const char *state = "a stiff";
const char *action = "voom";
const char *type = "Norwegian Blue";
static char *kwlist[] = {"voltage", "state", "action", "type", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|sss", kwlist,
&voltage, &state, &action, &type))
return NULL;
printf("-- This parrot wouldn't %s if you put %i Volts through it.\n",
action, voltage);
printf("-- Lovely plumage, the %s -- It's %s!\n", type, state);
Py_RETURN_NONE;
}
static PyMethodDef keywdarg_methods[] = {
/* The cast of the function is necessary since PyCFunction values
* only take two PyObject* parameters, and keywdarg_parrot() takes
* three.
*/
{"parrot", (PyCFunction)(void(*)(void))keywdarg_parrot, METH_VARARGS | METH_KEYWORDS,
"Print a lovely skit to standard output."},
{NULL, NULL, 0, NULL} /* sentinel */
};
static struct PyModuleDef keywdarg_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "keywdarg",
.m_size = 0,
.m_methods = keywdarg_methods,
};
PyMODINIT_FUNC
PyInit_keywdarg(void)
{
return PyModuleDef_Init(&keywdarg_module);
}
1.9. ä»»æã®å€ãæ§ç¯ãã¶
Py_BuildValue() 㯠PyArg_ParseTuple() ã®å¯Ÿæ¥µã«äœçœ®ãããã®ã§ãããã®é¢æ°ã¯ä»¥äžã®ããã«å®çŸ©ãããŠããŸã:
PyObject *Py_BuildValue(const char *format, ...);
Py_BuildValue() ã¯ã PyArg_ParseTuple() ã®èªèããäžé£ã®æžåŒåäœã«äŒŒãæžåŒåäœãèªèããŸãããã ã (颿°ãžã®åºåã§ã¯ãªããå
¥åã«äœ¿ããã) åŒæ°ã¯ãã€ã³ã¿ã§ã¯ãªãããã ã®å€ã§ãªããã°ãªããŸããã Python ããåŒã³åºããã C 颿°ãè¿ãå€ãšããŠé©åãªãæ°ã㪠Python ãªããžã§ã¯ããè¿ããŸãã
PyArg_ParseTuple() ãšã¯äžã€éãç¹ããããŸã: PyArg_ParseTuple() ã¯ç¬¬äžåŒæ°ãã¿ãã«ã«ããå¿
èŠããããŸã (Python ã®åŒæ°ãªã¹ãã¯å
éšçã«ã¯åžžã«ã¿ãã«ãšããŠè¡šçŸãããããã§ã) ãã Py_BuildValue() ã¯ã¿ãã«ãçæãããšã¯éããŸããã Py_BuildValue() ã¯æžåŒæååäžã«æžåŒåäœãäºã€ããã以äžå
¥ã£ãŠããå Žåã«ã®ã¿ã¿ãã«ãæ§ç¯ããŸããæžåŒæååã空ãªãã None ãè¿ããŸãããã£ããäžã€ã®æžåŒåäœãªãããã®æžåŒåäœãèšè¿°ããŠããäœããã®ãªããžã§ã¯ãã«ãªããŸãããµã€ãºã 0 ã 1 ã®ã¿ãã«è¿ããããã®ãªããæžåŒæååãäžžæ¬åŒ§ã§å²ããŸãã
以äžã«äŸã瀺ããŸã (å·Šã«åŒã³åºãäŸããå³ã«æ§ç¯ããã Python å€ã瀺ããŸã):
Py_BuildValue("") None
Py_BuildValue("i", 123) 123
Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)
Py_BuildValue("s", "hello") 'hello'
Py_BuildValue("y", "hello") b'hello'
Py_BuildValue("ss", "hello", "world") ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("y#", "hello", 4) b'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))
1.10. åç §ã«ãŠã³ãæ³Â¶
C ã C++ã®ãããªèšèªã§ã¯ãããã°ã©ãã¯ããŒãäžã®ã¡ã¢ãªãåçã«ç¢ºä¿ãããè§£æŸããããã責任ããããŸããããããäœæ¥ã¯ C ã§ã¯é¢æ° malloc() ã free() ã§è¡ããŸããC++ã§ã¯æ¬è³ªçã«åãæå³ã§æŒç®å new ã delete ã䜿ãããŸããããã§ã以äžã®è°è«ã¯ C ã®å Žåã«éå®ããŠè¡ããŸãã
Every block of memory allocated with malloc() should eventually be
returned to the pool of available memory by exactly one call to free().
It is important to call free() at the right time. If a block's address
is forgotten but free() is not called for it, the memory it occupies
cannot be reused until the program terminates. This is called a memory
leak. On the other hand, if a program calls free() for a block and then
continues to use the block, it creates a conflict with reuse of the block
through another malloc() call. This is called using freed memory.
It has the same bad consequences as referencing uninitialized data --- core
dumps, wrong results, mysterious crashes.
ããããã¡ã¢ãªãªãŒã¯ã®åå ã¯ã³ãŒãäžã®æ®éã§ãªãåŠççµè·¯ã§ããäŸãã°ããã颿°ãããã¡ã¢ãªãããã¯ã確ä¿ããäœããã®èšç®ãè¡ã£ãŠãå床ãããã¯ãè§£æŸãããšããŸããããŠã颿°ã®èŠæ±ä»æ§ã倿ŽããŠãèšç®ã«å¯Ÿãããã¹ãã远å ãããšããšã©ãŒæ¡ä»¶ãæ€åºãã颿°ã®éäžã§åŠçãæ»ãããã«ãªããããããŸããããã®éäžã§ã®çµäºãèµ·ãããšãã確ä¿ãããã¡ã¢ãªãããã¯ã¯è§£æŸãå¿ããããã®ã§ããã³ãŒããåŸã§è¿œå ãããå Žåã«ã¯ç¹ã«ããã§ãããã®ãããªã¡ã¢ãªãªãŒã¯ãäžæŠçŽã蟌ãã§ããŸããšãé·ã鿀åºãããªããŸãŸã«ãªãããšããããããŸã: ãšã©ãŒã«ãã颿°ã®çµäºã¯ãå šãŠã®é¢æ°åŒã³åºãã®ã«å¯ŸããŠã»ãã®ããããªå²åããèµ·ããããã®äžæ¹ã§ã»ãšãã©ã®è¿ä»£çãªèšç®æ©ã¯çžåœéã®ä»®æ³èšæ¶ãæã£ãŠãããããã¡ã¢ãªãªãŒã¯ãæããã«ãªãã®ã¯ãé·ãéåäœããŠããããã»ã¹ããªãŒã¯ãèµ·ãã颿°ãäœåºŠã䜿ã£ãå Žåã«éãããããã§ããåŸã£ãŠããã®çš®ã®ãšã©ãŒãæå°éã«ãšã©ãããããªã³ãŒãã£ã³ã°èŠçŽãæŠç¥ãèšããŠãäžæ ®ã®ã¡ã¢ãªãªãŒã¯ãé¿ããããšãéèŠãªã®ã§ãã
Python 㯠malloc() ã free() ãéåžžã«ããå©çšãããããã¡ã¢ãªãªãŒã¯ã®é²æ¢ã«å ããè§£æŸãããã¡ã¢ãªã®äœ¿çšã鲿¢ããæŠç¥ãå¿
èŠã§ãããã®ããã«éžã°ããã®ãåç
§ã«ãŠã³ãæ³ (reference counting) ãšåŒã°ããææ³ã§ããåç
§ã«ãŠã³ãæ³ã®åçã¯ç°¡åã§ã: å
šãŠã®ãªããžã§ã¯ãã«ã¯ã«ãŠã³ã¿ãããããªããžã§ã¯ãã«å¯Ÿããåç
§ãã©ããã«ä¿åããããã«ãŠã³ã¿ãã€ã³ã¯ãªã¡ã³ããããªããžã§ã¯ãã«å¯Ÿããåç
§ãåé€ãããããã¯ãªã¡ã³ãããŸããã«ãŠã³ã¿ããŒãã«ãªã£ããããªããžã§ã¯ããžã®æåŸã®åç
§ãåé€ãããããšã«ãªãããªããžã§ã¯ãã¯è§£æŸãããŸãã
An alternative strategy is called automatic garbage collection.
(Sometimes, reference counting is also referred to as a garbage collection
strategy, hence the use of "automatic" to distinguish the two.) The big
advantage of automatic garbage collection is that the user doesn't need to call
free() explicitly. (Another claimed advantage is an improvement in speed
or memory usage --- this is no hard fact however.) The disadvantage is that for
C, there is no truly portable automatic garbage collector, while reference
counting can be implemented portably (as long as the functions malloc()
and free() are available --- which the C Standard guarantees). Maybe some
day a sufficiently portable automatic garbage collector will be available for C.
Until then, we'll have to live with reference counts.
Python ã§ã¯ãäŒçµ±çãªåç §ã«ãŠã³ãæ³ã®å®è£ ãè¡ã£ãŠããäžæ¹ã§ãåç §ã®åŸªç°ãæ€åºããããã«åã埪ç°åç §æ€åºæ©æ§ (cycle detector) ãæäŸããŠããŸãã埪ç°åç §æ€åºæ©æ§ã®ãããã§ãçŽæ¥ã鿥ã«ããããã埪ç°åç §ã®çæãæ°ã«ããã«ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸã; ãšããã®ããåç §ã«ãŠã³ãæ³ã ãã䜿ã£ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³å®è£ ã«ãšã£ãŠåŸªç°åç §ã¯åŒ±ç¹ã ããã§ãã埪ç°åç §ã¯ã(鿥åç §ã®å Žåãå«ããŠ) çžäºãžã®åç §ãå ¥ã£ããªããžã§ã¯ããã圢æãããããã埪ç°å ã®ãªããžã§ã¯ãã¯åã éãŒãã®åç §ã«ãŠã³ããæã¡ãŸããå žåçãªåç §ã«ãŠã³ãæ³ã®å®è£ ã§ã¯ãããšã埪ç°åç §ã圢æãããªããžã§ã¯ãã«å¯ŸããŠä»ã«å šãåç §ããªããšããŠãã埪ç°åç §å ã®ã©ã®ãªããžã§ã¯ãã«å±ããã¡ã¢ãªãåå©çšã§ããŸããã
埪ç°åç
§æ€åºæ©æ§ã¯ãã®ãããªã¬ããŒãžãµã€ã¯ã« (åè¿°ãããããªåŸªç°åç
§ãªããžã§ã¯ã) ãæ€åºããŠååããããšãã§ããŸãã
gc ã¢ãžã¥ãŒã«ãã®ãããªæ€åºæ©æ§ã®å®è¡ (collect() 颿°) ãæäŸãããšãšãã«ãèšå®ã®ããã®ã€ã³ã¿ãã§ãŒã¹ããã³æ€åºæ©æ§ãå®è¡æã«ç¡å¹ã«ããæ¹æ³ãæäŸããŠããŸãã
1.10.1. Python ã«ãããåç §ã«ãŠã³ãæ³Â¶
Python ã«ã¯ãåç
§ã«ãŠã³ãã®ã€ã³ã¯ãªã¡ã³ãããã¯ãªã¡ã³ããåŠçããäºã€ã®ãã¯ãã Py_INCREF(x) ãš Py_DECREF(x) ããããŸãã Py_DECREF() ã¯ãåç
§ã«ãŠã³ãããŒãã«å°éããéã«ããªããžã§ã¯ãã®ã¡ã¢ãªè§£æŸãè¡ããŸããæè»æ§ãæãããããã«ã free() ãçŽæ¥åŒã³åºããŸãã --- ãã®ä»£ããã«ãªããžã§ã¯ãã®åãªããžã§ã¯ã (type object) ãä»ããŸãããã®ããã« (ä»ã®ç®çããããŸãã)ãå
šãŠã®ãªããžã§ã¯ãã«ã¯èªèº«ã®åãªããžã§ã¯ãã«å¯Ÿãããã€ã³ã¿ãå
¥ã£ãŠããŸãã
ããŠããŸã é倧ãªçåãæ®ã£ãŠããŸã: ã〠Py_INCREF(x) ã Py_DECREF(x) ã䜿ãã°ããã®ã§ãããã? ãŸããããã€ãã®çšèªèª¬æããå§ããããŠãã ããããŸãããªããžã§ã¯ã㯠"å æ (own)" ãããããšã¯ãããŸãã; ãããããããªããžã§ã¯ãã«å¯Ÿããåç
§ã®ææ own a reference ã¯ã§ããŸãããªããžã§ã¯ãã®åç
§ã«ãŠã³ãã¯ããã®ãªããžã§ã¯ããåç
§ã®ææãåããŠããåæ°ãšå®çŸ©ãããŠããŸããåç
§ã®ææè
ã¯ãåç
§ãå¿
èŠãªããªã£ãéã« Py_DECREF() ãåŒã³åºã圹å²ãæ
ããŸããåç
§ã®æææš©ã¯å§è² (transfer) ã§ããŸããææåç
§ (owned reference) ã®æŸæ£ã«ã¯ãæž¡ããä¿åããã Py_DECREF() ãåŒã³åºãããšããäžã€ã®æ¹æ³ããããŸããææåç
§ãåŠçãå¿ãããšãã¡ã¢ãªãªãŒã¯ãåŒãèµ·ãããŸãã
It is also possible to borrow [2] a reference to an object. The
borrower of a reference should not call Py_DECREF(). The borrower must
not hold on to the object longer than the owner from which it was borrowed.
Using a borrowed reference after the owner has disposed of it risks using freed
memory and should be avoided completely [3].
åç §ã®åçšãåç §ã®ææãããåªããŠããç¹ã¯ãã³ãŒãããšãããããããåŠççµè·¯ã§åç §ã廿£ããŠããããæ³šæããªããŠæžãããšã§ã --- å¥ã®èšãæ¹ãããã°ãåçšåç §ã®å Žåã«ã¯ãåŠçã®éäžã§é¢æ°ãçµäºããŠãã¡ã¢ãªãªãŒã¯ã®å±éºãåãããšããªãããšããããšã§ããéã«ãææãããäžå©ãªç¹ã¯ããããŸãšãã«èŠããã³ãŒãããå®éã«ã¯åç §ã®åçšå ã§æŸæ£ãããŠããŸã£ãåŸã«ãã®åç §ã䜿ããããããªããããªåŸ®åŠãªç¶æ³ããããšããããšã§ãã
Py_INCREF() ãåŒã³åºããšãåçšåç
§ãææåç
§ã«å€æŽã§ããŸãããã®æäœã¯åç
§ã®åçšå
ã®ç¶æ
ã«ã¯åœ±é¿ããŸãã --- Py_INCREF() ã¯æ°ããªææåç
§ãçæããåç
§ã®ææè
ãæ
ãã¹ãå
šãŠã®è²¬ä»»ã課ããŸã (ã€ãŸããæ°ããªåç
§ã®ææè
ã¯ã以åã®ææè
ãšåæ§ãåç
§ã®æŸæ£ãé©åã«è¡ããã°ãªããŸãã)ã
1.10.2. æææš©ã«ãŸã€ããèŠå¶
ãªããžã§ã¯ããžã®åç §ã颿°ã®å å€ã«æž¡ãå Žåã«ã¯ããªããžã§ã¯ãã®æææš©ãåç §ãšå ±ã«æž¡ããããåŠããåžžã«é¢æ°ã€ã³ã¿ãŒãã§ãŒã¹ä»æ§ã®äžéšãšãªããŸãã
ãªããžã§ã¯ããžã®åç
§ãè¿ãã»ãšãã©ã®é¢æ°ã¯ãåç
§ãšãšãã«æææš©ãæž¡ããŸããç¹ã«ã PyLong_FromLong() ã Py_BuildValue() ã®ããã«ãæ°ãããªããžã§ã¯ããçæãã颿°ã¯å
šãŠæææš©ãçžæã«æž¡ããŸãããªããžã§ã¯ããå®éã«ã¯æ°ããªãªããžã§ã¯ãã§ãªããŠãããã®ãªããžã§ã¯ãã«å¯Ÿããæ°ããªåç
§ã®æææš©ãåŸãŸããäŸãã°ã PyLong_FromLong() ã¯ãã䜿ãå€ããã£ãã·ã¥ããŠããããã£ãã·ã¥ãããå€ãžã®åç
§ãè¿ãããšããããŸãã
PyObject_GetAttrString() ã®ããã«ããããªããžã§ã¯ãããå¥ã®ãªããžã§ã¯ããæœåºãããããªé¢æ°ããŸããåç
§ãšãšãã«æææš©ãå§è²ããŸãããã¡ãã®æ¹ã¯ããçè§£ãã«ãããããããŸããããšããã®ã¯ãã䜿ãããã«ãŒãã³ã®ããã€ããäŸå€ãšãªã£ãŠããããã§ã: PyTuple_GetItem() ã PyList_GetItem() ã PyDict_GetItem() ãããã³ PyDict_GetItemString() ã¯å
šãŠãã¿ãã«ããªã¹ãããŸãã¯èŸæžããåçšåç
§ãè¿ããŸãã
PyImport_AddModule() ã¯ãå®éã«ã¯ãªããžã§ã¯ããçæããŠè¿ãããšãããã«ãããããããåçšåç
§ãè¿ããŸã: ãããå¯èœãªã®ã¯ãçæããããªããžã§ã¯ãã«å¯Ÿããææåç
§ã¯ sys.modules ã«ä¿æãããããã§ãã
ãªããžã§ã¯ããžã®åç
§ãå¥ã®é¢æ°ã«æž¡ãå Žåãäžè¬çã«ã¯ã颿°åŽã¯åŒã³åºãæããåç
§ãåçšããŸã --- åç
§ãä¿åããå¿
èŠããããªãã颿°åŽã¯ Py_INCREF() ãåŒã³åºããŠç¬ç«ããææè
ã«ãªããŸãããšã¯ããããã®èŠåã«ã¯äºã€ã®éèŠãªäŸå€: PyTuple_SetItem() ãš PyList_SetItem() ããããŸãããããã®é¢æ°ã¯ãæž¡ãããåŒæ°èŠçŽ ã«å¯ŸããŠæææš©ãä¹ã£åã (take over) ãŸã --- ããšã倱æããŠãã§ã! (PyDict_SetItem() ãšãã®ä»²éã¯æææš©ãä¹ã£åããŸãã --- ãããã¯ããã° "æ®éã®" 颿°ã§ãã)
Python ãã C 颿°ãåŒã³åºãããéã«ã¯ãC 颿°ã¯åŒã³åºãåŽããåŒæ°ãžã®åç
§ãåçšããŸããC 颿°ã®åŒã³åºãåŽã¯ãªããžã§ã¯ããžã®åç
§ãææããŠããã®ã§ãåçšåç
§ã®çåæéãä¿èšŒãããã®ã¯é¢æ°ãåŠçãè¿ããŸã§ã§ãããã®ããã«ããŠåçšåç
§ãä¿åãããä»ã«æž¡ããããããå Žåã«ã®ã¿ã Py_INCREF() ã䜿ã£ãŠææåç
§ã«ããå¿
èŠããããŸãã
Python ããåŒã³åºããã C 颿°ãè¿ãåç §ã¯ææåç §ã§ãªããã°ãªããŸãã --- æææš©ã¯é¢æ°ããåŒã³åºãåŽãžãšå§è²ãããŸãã
1.10.3. èæ°·Â¶
æ°å°ãªãç¶æ³ã«ãããŠãäžèŠç¡å®³ã«èŠããåçšåç §ã®å©çšãåé¡ãã²ããããããšããããŸãããã®åé¡ã¯ãã¹ãŠãã€ã³ã¿ããªã¿ãéæç€ºçã«åŒã³åºãããã€ã³ã¿ããªã¿ãåç §ã®ææè ã«åç §ãæŸæ£ãããŠããŸãç¶æ³ãšé¢ä¿ããŠããŸãã
ç¥ã£ãŠããã¹ãã±ãŒã¹ã®ãã¡æåã®ããããŠæãéèŠãªãã®ã¯ããªã¹ãèŠçŽ ã«å¯Ÿããåç
§ãåããŠããéã«èµ·ãããé¢ä¿ãªããªããžã§ã¯ãã«å¯Ÿãã Py_DECREF() ã®äœ¿çšã§ããäŸãã°:
void
bug(PyObject *list)
{
PyObject *item = PyList_GetItem(list, 0);
PyList_SetItem(list, 1, PyLong_FromLong(0L));
PyObject_Print(item, stdout, 0); /* BUG! */
}
äžã®é¢æ°ã¯ãŸãã list[0] ãžã®åç
§ãåçšããæ¬¡ã« list[1] ãå€ 0 ã§çœ®ãæããæåŸã«ããã»ã©åçšããåç
§ãåºåããŠããŸããäœãåé¡ãªãããã«èŠããŸãã? ã§ãããã§ã¯ãªãã®ã§ã!
Let's follow the control flow into PyList_SetItem(). The list owns
references to all its items, so when item 1 is replaced, it has to dispose of
the original item 1. Now let's suppose the original item 1 was an instance of a
user-defined class, and let's further suppose that the class defined a
__del__() method. If this class instance has a reference count of 1,
disposing of it will call its __del__() method. Internally,
PyList_SetItem() calls Py_DECREF() on the replaced item,
which invokes replaced item's corresponding
tp_dealloc function. During
deallocation, tp_dealloc calls
tp_finalize, which is mapped to the
__del__() method for class instances (see PEP 442). This entire
sequence happens synchronously within the PyList_SetItem() call.
Since it is written in Python, the __del__() method can execute arbitrary
Python code. Could it perhaps do something to invalidate the reference to
item in bug()? You bet! Assuming that the list passed into
bug() is accessible to the __del__() method, it could execute a
statement to the effect of del list[0], and assuming this was the last
reference to that object, it would free the memory associated with it, thereby
invalidating item.
åé¡ã®åå ãåããã°ã解決ã¯ç°¡åã§ããäžæçã«åç §åæ°ãå¢ããã°ããã®ã§ããæ£ããåäœããããŒãžã§ã³ã¯ä»¥äžã®ããã«ãªããŸã:
void
no_bug(PyObject *list)
{
PyObject *item = PyList_GetItem(list, 0);
Py_INCREF(item);
PyList_SetItem(list, 1, PyLong_FromLong(0L));
PyObject_Print(item, stdout, 0);
Py_DECREF(item);
}
This is a true story. An older version of Python contained variants of this bug
and someone spent a considerable amount of time in a C debugger to figure out
why his __del__() methods would fail...
The second case of problems with a borrowed reference is a variant involving
threads. Normally, multiple threads in the Python interpreter can't get in each
other's way, because there is a global lock
protecting Python's entire object space.
However, it is possible to temporarily release this lock using the macro
Py_BEGIN_ALLOW_THREADS, and to re-acquire it using
Py_END_ALLOW_THREADS. This is common around blocking I/O calls, to
let other threads use the processor while waiting for the I/O to complete.
Obviously, the following function has the same problem as the previous one:
void
bug(PyObject *list)
{
PyObject *item = PyList_GetItem(list, 0);
Py_BEGIN_ALLOW_THREADS
...some blocking I/O call...
Py_END_ALLOW_THREADS
PyObject_Print(item, stdout, 0); /* BUG! */
}
1.10.4. NULL ãã€ã³ã¿Â¶
äžè¬è«ãšããŠããªããžã§ã¯ããžã®åç
§ãåŒæ°ã«ãšã颿°ã¯ãŠãŒã¶ã NULL ãã€ã³ã¿ãæž¡ããšã¯äºæ³ããŠããããæž¡ãããšãããšã³ã¢ãã³ãã«ãªã (ããããšã§ã³ã¢ãã³ããåŒãèµ·ãã) ããšã§ããããäžæ¹ããªããžã§ã¯ããžã®åç
§ãè¿ããããªé¢æ°ã¯äžè¬ã«ãäŸå€ã®çºçã瀺ãå Žåã«ã®ã¿ NULL ãè¿ããŸããåŒæ°ã«å¯Ÿã㊠NULL ãã¹ããè¡ããªãçç±ã¯ã颿°ã¯ãã°ãã°åãåã£ããªããžã§ã¯ããä»ã®é¢æ°ãžãšåŒãæž¡ãããã§ã --- åã
ã®é¢æ°ã NULL ãã¹ããè¡ãã°ãåé·ãªãã¹ãã倧éã«è¡ãããã³ãŒãã¯ããäœéã«åãããšã«ãªããŸãã
åŸã£ãŠã NULL ã®ãã¹ãã¯ãªããžã§ã¯ãã® "çºçæº"ãããªãã¡å€ã NULL ã«ãªããããããªããã€ã³ã¿ãåãåã£ããšãã ãã«ããŸãããã malloc() ããäŸå€ãéåºããå¯èœæ§ã®ãã颿°ããã®äŸã§ãã
ãã¯ã Py_INCREF() ããã³ Py_DECREF() 㯠NULL ãã€ã³ã¿ã®ãã§ãã¯ãè¡ããŸãã --- ãããããããã®ãã¯ãã®å€å圢ã§ãã Py_XINCREF() ããã³ Py_XDECREF() ã¯ãã§ãã¯ãè¡ããŸãã
ç¹å®ã®ãªããžã§ã¯ãåã«ã€ããŠèª¿ã¹ããã¯ã (Pytype_Check()) 㯠NULL ãã€ã³ã¿ã®ãã§ãã¯ãè¡ããŸãã --- ç¹°ãè¿ããŸãããæ§ã
ãªç°ãªãåãæ³å®ããŠãªããžã§ã¯ãã®åã調ã¹ãéã«ã¯ããããããã¯ããç¶ããŠåŒã³åºãå¿
èŠãããã®ã§ãåå¥ã« NULL ãã€ã³ã¿ã®ãã§ãã¯ããããšåé·ãªãã¹ãã«ãªã£ãŠããŸãã®ã§ããåã調ã¹ããã¯ãã«ã¯ã NULL ãã§ãã¯ãè¡ãå€å圢ã¯ãããŸããã
The C function calling mechanism guarantees that the argument list passed to C
functions (args in the examples) is never NULL --- in fact it guarantees
that it is always a tuple [4].
NULL ãã€ã³ã¿ã Python ãŠãŒã¶ã¬ãã«ã« "éãã" ãŠããŸããšãæ·±å»ãªãšã©ãŒãåŒãèµ·ãããŸãã
1.11. C++ã§ã®æ¡åŒµã¢ãžã¥ãŒã«äœæÂ¶
C++ã§ãæ¡åŒµã¢ãžã¥ãŒã«ã¯äœæã§ããŸãããã ãããã€ãå¶éããããŸããã¡ã€ã³ããã°ã©ã (Python ã€ã³ã¿ããªã¿) 㯠C ã³ã³ãã€ã©ã§ã³ã³ãã€ã«ãããªã³ã¯ãããŠããã®ã§ãã°ããŒãã«å€æ°ãéçãªããžã§ã¯ããã³ã³ã¹ãã©ã¯ã¿ã§äœæã§ããŸãããã¡ã€ã³ããã°ã©ã ã C++ ã³ã³ãã€ã©ã§ãªã³ã¯ãããŠãããªãããã¯åé¡ã§ã¯ãããŸããã Python ã€ã³ã¿ããªã¿ããåŒã³åºããã颿° (ç¹ã«ã¢ãžã¥ãŒã«åæå颿°) ã¯ã extern "C" ã䜿ã£ãŠå®£èšããªããã°ãªããŸããããŸããPython ããããã¡ã€ã«ã extern "C" {...} ã«å
¥ããå¿
èŠã¯ãããŸãã--- ã·ã³ãã« __cplusplus (æè¿ã® C++ ã³ã³ãã€ã©ã¯å
šãŠãã®ã·ã³ãã«ãå®çŸ©ããŠããŸã) ãå®çŸ©ãããŠãããšãã« extern "C" {...} ãè¡ãããããã«ãããããã¡ã€ã«å
ã«ãã§ã«æžãããŠããããã§ãã
1.12. æ¡åŒµã¢ãžã¥ãŒã«ã« C API ãæäŸãã¶
å€ãã®æ¡åŒµã¢ãžã¥ãŒã«ã¯åã« Python ãã䜿ããæ°ããªé¢æ°ãåãæäŸããã ãã§ãããæã«æ¡åŒµã¢ãžã¥ãŒã«å ã®ã³ãŒããä»ã®æ¡åŒµã¢ãžã¥ãŒã«ã§ã䟿å©ãªããšããããŸããäŸãã°ãããã¢ãžã¥ãŒã«ã§ã¯é åºæŠå¿µã®ãªããªã¹ãã®ããã«åäœãã "ã³ã¬ã¯ã·ã§ã³ (collection)" ã¯ã©ã¹ãå®è£ ããŠãããããããŸãããã¡ããã©ãªã¹ããçæãããæäœãããã§ãã C API ãåããæšæºã® Python ãªã¹ãåã®ããã«ããã®æ°ããªã³ã¬ã¯ã·ã§ã³åãä»ã®æ¡åŒµã¢ãžã¥ãŒã«ããçŽæ¥æäœã§ããããã«ããã«ã¯äžé£ã® C 颿°ãæã£ãŠããªããã°ãªããŸããã
äžèŠãããšããã¯ç°¡åãªããš: åã«é¢æ°ã (ãã¡ãã static ãªã©ãšã¯å®£èšããã«) æžããŠãé©åãªããããã¡ã€ã«ãæäŸããC API ãæžãã°ããã ããã«æããŸãããããŠå®éã®ãšãããå
šãŠã®æ¡åŒµã¢ãžã¥ãŒã«ã Python ã€ã³ã¿ããªã¿ã«åžžã«éçã«ãªã³ã¯ãããŠããå Žåã«ã¯ããŸãåäœããŸãããšãããã¢ãžã¥ãŒã«ãå
±æã©ã€ãã©ãªã®å Žåã«ã¯ãäžã€ã®ã¢ãžã¥ãŒã«ã§å®çŸ©ãããŠããã·ã³ãã«ãä»ã®ã¢ãžã¥ãŒã«ããäžå¯èŠãªããšããããŸããå¯èŠæ§ã®è©³çްã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ãããŸã; ããã·ã¹ãã 㯠Python ã€ã³ã¿ããªã¿ãšå
šãŠã®æ¡åŒµã¢ãžã¥ãŒã«çšã«åäžã®ã°ããŒãã«ãªåå空éãçšæããŠããŸã (äŸãã° Windows)ãå¥ã®ã·ã¹ãã ã¯ã¢ãžã¥ãŒã«ã®ãªã³ã¯æã«åã蟌ãŸããã·ã³ãã«ãæç€ºçã«æå®ããå¿
èŠããããŸã (AIX ããã®äžäŸã§ã)ããŸãå¥ã®ã·ã¹ãã (ã»ãšãã©ã® Unix) ã§ã¯ãéã£ãæŠç¥ãéžæè¢ãšããŠæäŸããŠããŸãããããŠãããšãã·ã³ãã«ãã°ããŒãã«å€æ°ãšããŠå¯èŠã§ãã£ãŠããåŒã³åºããã颿°ã®å
¥ã£ãã¢ãžã¥ãŒã«ããŸã ããŒããããŠããªãããšã ã£ãŠãããŸã!
Portability therefore requires not to make any assumptions about symbol
visibility. This means that all symbols in extension modules should be declared
static, except for the module's initialization function, in order to
avoid name clashes with other extension modules (as discussed in section
The Module's Method Table and Initialization Function). And it means that symbols that should be accessible from
other extension modules must be exported in a different way.
Python ã¯ããæ¡åŒµã¢ãžã¥ãŒã«ã® C ã¬ãã«ã®æ å ± (ãã€ã³ã¿) ãå¥ã®ã¢ãžã¥ãŒã«ã«æž¡ãããã®ç¹æ®ãªæ©æ§: Capsule (ã«ãã»ã«)ãæäŸããŠããŸãã Capsule ã¯ãã€ã³ã¿ (void*) ãèšæ¶ãã Python ã®ããŒã¿åã§ãã Capsule 㯠C API ãä»ããŠã®ã¿çæãããã¢ã¯ã»ã¹ãããã§ããŸãããä»ã® Python ãªããžã§ã¯ããšåãããã«åãæž¡ãã§ããŸãããšããããCapsule ã¯æ¡åŒµã¢ãžã¥ãŒã«ã®åå空éå ã«ããååã«ä»£å ¥ã§ããŸããä»ã®æ¡åŒµã¢ãžã¥ãŒã«ã¯ãã®ã¢ãžã¥ãŒã«ã import ã§ããæ¬¡ã«ååãååŸããæåŸã«Capsule ãžã®ãã€ã³ã¿ãååŸããŸãã
æ¡åŒµã¢ãžã¥ãŒã«ã® C API ãå ¬éããããã«ãæ§ã ãªæ¹æ³ã§ Capsule ã䜿ãããŸããå颿°ã1ã€ã®ãªããžã§ã¯ãã«å ¥ããããå šãŠã® C API ã®ãã€ã³ã¿é åã Capsule ã«å ¥ããããšãã§ããŸãããããŠããã€ã³ã¿ã«å¯Ÿããä¿åãååŸãšãã£ãæ§ã ãªäœæ¥ã¯ãã³ãŒããæäŸããŠããã¢ãžã¥ãŒã«ãšã¯ã©ã€ã¢ã³ãã¢ãžã¥ãŒã«ãšã®éã§ã¯ç°ãªãæ¹æ³ã§åæ£ã§ããŸãã
ã©ã®æ¹æ³ãéžã¶ã«ããŠãã Capsule ã® name ãæ£ããèšå®ããããšã¯éèŠã§ãã PyCapsule_New() 㯠name åŒæ° (const char*) ãåããŸãã NULL ã name ã«æž¡ãããšãèš±å¯ãããŠããŸããã name ãèšå®ããããšãåŒ·ãæšå¥šããŸããæ£ããååãä»ãããã Capsule ã¯ããçšåºŠã®å®è¡æåå®å
šæ§ãæã¡ãŸããååãä»ããããŠããªã Capsule ãä»ã® Capsule ãšåºå¥ããçŸå®çãªæ¹æ³ã¯ãããŸããã
ç¹ã«ã C API ãå ¬éããããã® Capsule ã«ã¯æ¬¡ã®ã«ãŒã«ã«åŸã£ãååãä»ããã¹ãã§ã:
modulename.attributename
PyCapsule_Import() ãšãã䟿å©é¢æ°ã¯ã Capsule ã®ååããã®ã«ãŒã«ã«äžèŽããŠãããšãã«ã®ã¿ãç°¡åã« Capsule çµç±ã§å
¬éãããŠãã C API ãããŒãããããšãã§ããŸãããã®æåã«ããã C API ã®ãŠãŒã¶ãŒãã確å®ã«æ£ãã C API ãæ ŒçŽããŠãã Capsule ãããŒãã§ããããšã確ãããããšãã§ããŸãã
以äžã®äŸã§ã¯ãååãå ¬éããã¢ãžã¥ãŒã«ã®äœè ã«ã»ãšãã©ã®è² è·ãæãããŸããããã䜿ãããã©ã€ãã©ãªãäœãéã«é©åãªã¢ãããŒãã宿ŒããŸãããã®ã¢ãããŒãã§ã¯ãå šãŠã® C API ãã€ã³ã¿ (äŸäžã§ã¯äžã€ã ãã§ãã!) ãã Capsule ã®å€ãšãªã void ãã€ã³ã¿ã®é åã«ä¿åããŸããæ¡åŒµã¢ãžã¥ãŒã«ã«å¯Ÿå¿ããããããã¡ã€ã«ã¯ãã¢ãžã¥ãŒã«ã® import ãš C API ãã€ã³ã¿ãååŸããããæé ãããã¯ããæäŸããŸã; ã¯ã©ã€ã¢ã³ãã¢ãžã¥ãŒã«ã¯ãC API ã«ã¢ã¯ã»ã¹ããåã«ãã®ãã¯ããåŒã¶ã ãã§ãã
The exporting module is a modification of the spam module from section
A Simple Example. The function spam.system() does not call
the C library function system() directly, but a function
PySpam_System(), which would of course do something more complicated in
reality (such as adding "spam" to every command). This function
PySpam_System() is also exported to other extension modules.
The function PySpam_System() is a plain C function, declared
static like everything else:
static int
PySpam_System(const char *command)
{
return system(command);
}
The function spam_system() is modified in a trivial way:
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = PySpam_System(command);
return PyLong_FromLong(sts);
}
ã¢ãžã¥ãŒã«ã®å é ã«ãã以äžã®è¡
#include <Python.h>
ã®çŽåŸã«ã以äžã®äºè¡ãå¿ ã远å ããŠãã ãã:
#define SPAM_MODULE
#include "spammodule.h"
The #define is used to tell the header file that it is being included in the
exporting module, not a client module. Finally, the module's mod_exec function must take care of initializing the C API pointer array:
static int
spam_module_exec(PyObject *m)
{
static void *PySpam_API[PySpam_API_pointers];
PyObject *c_api_object;
/* Initialize the C API pointer array */
PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
/* Create a Capsule containing the API pointer array's address */
c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
return -1;
}
return 0;
}
Note that PySpam_API is declared static; otherwise the pointer
array would disappear when PyInit_spam() terminates!
ããããã®å€§éšåã¯ããããã¡ã€ã« spammodule.h å
ã«ããã以äžã®ããã«ãªã£ãŠããŸã:
#ifndef Py_SPAMMODULE_H
#define Py_SPAMMODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Header file for spammodule */
/* C API functions */
#define PySpam_System_NUM 0
#define PySpam_System_RETURN int
#define PySpam_System_PROTO (const char *command)
/* Total number of C API pointers */
#define PySpam_API_pointers 1
#ifdef SPAM_MODULE
/* This section is used when compiling spammodule.c */
static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;
#else
/* This section is used in modules that use spammodule's API */
static void **PySpam_API;
#define PySpam_System \
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
/* Return -1 on error, 0 on success.
* PyCapsule_Import will set an exception if there's an error.
*/
static int
import_spam(void)
{
PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
return (PySpam_API != NULL) ? 0 : -1;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* !defined(Py_SPAMMODULE_H) */
All that a client module must do in order to have access to the function
PySpam_System() is to call the function (or rather macro)
import_spam() in its mod_exec function:
static int
client_module_exec(PyObject *m)
{
if (import_spam() < 0) {
return -1;
}
/* additional initialization can happen here */
return 0;
}
ãã®ã¢ãããŒãã®äž»èŠãªæ¬ ç¹ã¯ã spammodule.h ãããé£è§£ã«ãªããšããããšã§ãããšã¯ãããå颿°ã®åºæ¬çãªæ§æã¯å
¬éããããã®ãšåããªã®ã§ãæžãæ¹ãäžåºŠã ãåŠã¹ã°ãã¿ãŸãã
Finally it should be mentioned that Capsules offer additional functionality,
which is especially useful for memory allocation and deallocation of the pointer
stored in a Capsule. The details are described in the Python/C API Reference
Manual in the section ã«ãã»ã« and in the implementation of Capsules (files
Include/pycapsule.h and Objects/capsule.c in the Python source
code distribution).
èæ³š