Jan 3, 2019 - 使用C或C++扩展Python(四)-定义扩展类(增加字段和函数)

原文:https://docs.python.org/3/extending/newtypes_tutorial.html

“使用C或C++扩展Python(四)-定义扩展类(增加字段和函数)”

/*
custom2.c
compile:gcc -fPIC -shared -I /usr/include/python3.5m/ custom2.c -o custom2.so
usage:
>>> import custom2
>>> mycustom = custom2.Custom()
>>> mycustom.first = 'lu'
>>> mycustom.last = 'ping'
>>> mycustom.name()
lu ping
reference:https://docs.python.org/3/extending/newtypes_tutorial.html
*/
#include <Python.h>
#include "structmember.h"

typedef struct {
    PyObject_HEAD
    PyObject *first; /* first name */
    PyObject *last;  /* last name */
    int number;
} CustomObject;

static void
Custom_dealloc(CustomObject *self)
{
    Py_XDECREF(self->first);
    Py_XDECREF(self->last);
    Py_TYPE(self)->tp_free((PyObject *) self);
}

static PyObject *
Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    CustomObject *self;
    self = (CustomObject *) type->tp_alloc(type, 0);
    if (self != NULL) {
        self->first = PyUnicode_FromString("");
        if (self->first == NULL) {
            Py_DECREF(self);
            return NULL;
        }
        self->last = PyUnicode_FromString("");
        if (self->last == NULL) {
            Py_DECREF(self);
            return NULL;
        }
        self->number = 0;
    }
    return (PyObject *) self;
}

static int
Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
{
    static char *kwlist[] = {"first", "last", "number", NULL};
    PyObject *first = NULL, *last = NULL, *tmp;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
                                     &first, &last,
                                     &self->number))
        return -1;

    if (first) {
        tmp = self->first;
        Py_INCREF(first);
        self->first = first;
        Py_XDECREF(tmp);
    }
    if (last) {
        tmp = self->last;
        Py_INCREF(last);
        self->last = last;
        Py_XDECREF(tmp);
    }
    return 0;
}

static PyMemberDef Custom_members[] = {
    {"first", T_OBJECT_EX, offsetof(CustomObject, first), 0,
     "first name"},
    {"last", T_OBJECT_EX, offsetof(CustomObject, last), 0,
     "last name"},
    {"number", T_INT, offsetof(CustomObject, number), 0,
     "custom number"},
    {NULL}  /* Sentinel */
};

static PyObject *
Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
{
    if (self->first == NULL) {
        PyErr_SetString(PyExc_AttributeError, "first");
        return NULL;
    }
    if (self->last == NULL) {
        PyErr_SetString(PyExc_AttributeError, "last");
        return NULL;
    }
    return PyUnicode_FromFormat("%S %S", self->first, self->last);
}

static PyMethodDef Custom_methods[] = {
    {"name", (PyCFunction) Custom_name, METH_NOARGS,
     "Return the name, combining the first and last name"
    },
    {NULL}  /* Sentinel */
};

static PyTypeObject CustomType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "custom2.Custom",
    .tp_doc = "Custom objects",
    .tp_basicsize = sizeof(CustomObject),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    .tp_new = Custom_new,
    .tp_init = (initproc) Custom_init,
    .tp_dealloc = (destructor) Custom_dealloc,
    .tp_members = Custom_members,
    .tp_methods = Custom_methods,
};

static PyModuleDef custommodule = {
    PyModuleDef_HEAD_INIT,
    .m_name = "custom2",
    .m_doc = "Example module that creates an extension type.",
    .m_size = -1,
};

PyMODINIT_FUNC
PyInit_custom2(void)
{
    PyObject *m;
    if (PyType_Ready(&CustomType) < 0)
        return NULL;

    m = PyModule_Create(&custommodule);
    if (m == NULL)
        return NULL;

    Py_INCREF(&CustomType);
    PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
    return m;
}

custom2没有限制字段的类型,你可以赋任何对象给first和last,下面的版本会改进这个问题。

Jan 2, 2019 - 使用C或C++扩展Python(三)-定义扩展类(基础篇)

原文:https://docs.python.org/3/extending/newtypes_tutorial.html

“使用C或C++扩展Python(三)-定义扩展类(基础篇)”

/*
custom.c
compile:gcc -fPIC -shared -I /usr/include/python3.5m/ custom.c -o custom.so
usage:
>>> import custom
>>> mycustom = custom.Custom()
reference:https://docs.python.org/3/extending/newtypes_tutorial.html
*/
#include <Python.h>

typedef struct {
    PyObject_HEAD
    /* Type-specific fields go here. */
} CustomObject;

static PyTypeObject CustomType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "custom.Custom",
    .tp_doc = "Custom objects",
    .tp_basicsize = sizeof(CustomObject),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = PyType_GenericNew,
};

static PyModuleDef custommodule = {
    PyModuleDef_HEAD_INIT,
    .m_name = "custom",
    .m_doc = "Example module that creates an extension type.",
    .m_size = -1,
};

PyMODINIT_FUNC
PyInit_custom(void)
{
    PyObject *m;
    if (PyType_Ready(&CustomType) < 0)
        return NULL;

    m = PyModule_Create(&custommodule);
    if (m == NULL)
        return NULL;

    Py_INCREF(&CustomType);
    PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
    return m;
}

Jan 2, 2019 - 使用C或C++扩展Python(二)-从C调用python

原文:https://docs.python.org/dev/extending/extending.html

“使用C或C++扩展Python(二)-从C调用python”

/*
spamcall.c
compile:gcc -fPIC -shared -I /usr/include/python3.5m/ spamcall.c -o spamcall.so
usage:
>>> import spamcall
>>> def func(a):
        print(a)
>>> spamcall.set_calllback(func)
>>> spamcall.call_it(123)
123
reference:https://docs.python.org/dev/extending/extending.html
*/
#include <Python.h>

static PyObject *my_callback = NULL;    // def func(a):

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);
        Py_XDECREF(my_callback);
        my_callback = temp;
        Py_INCREF(Py_None);
        result = Py_None;
    }
    return result;
}

static PyObject *
my_call_it(PyObject *dummy, PyObject *args)
{
    int arg;
    PyObject *arglist;
    PyObject *result;


    arg = 123;
    if (!PyArg_ParseTuple(args, "i", &arg))
        return NULL;
    arglist = Py_BuildValue("(i)", arg);
    result  = PyObject_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    if (result == NULL)
        return NULL;
    Py_DECREF(result);

    Py_RETURN_NONE;    // Py_INCREF(Py_None); return Py_None;
}

static PyMethodDef SpamMethods[] = {
    {"set_callback", my_set_callback, METH_VARARGS, "set a callback"},
    {"call_it", my_call_it, METH_VARARGS, "call it"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef spammodule = {
    PyModuleDef_HEAD_INIT,
    "spamcall",   /* name of module */
    "Example module that creates an extension type.", /* module documentation, may be NULL */
    -1,       /* size of per-interpreter state of the module,or -1 if the module keeps state in global variables. */
    SpamMethods
};

PyMODINIT_FUNC
PyInit_spamcall(void)
{
    PyObject *m;

    m = PyModule_Create(&spammodule);
    if (m == NULL)
        return NULL;
    return m;
}