C Numpy / C API的示例

/* dtlsmodule.c */
#include <math.h>
#include <stdio.h>

#include <Python.h>
#include "structmember.h"
#include <numpy/arrayobject.h>

/* ================================================================= MACROS */
#define QUOTE(s) # s   /* turn s into string "s" */
#define NDIM_CHECK(a, expected_ndim, rt_error)				\
  if (PyArray_NDIM(a) != expected_ndim) {				\
    PyErr_Format(PyExc_ValueError,					\
		 "%s array is %d-dimensional, but expected to be %d-dimensional", \
		 QUOTE(a), PyArray_NDIM(a), expected_ndim);		\
    return rt_error;							\
  }
#define DIM_CHECK(a, dim, expected_length, rt_error)			\
  if (dim > PyArray_NDIM(a)) {						\
    PyErr_Format(PyExc_ValueError,					\
		 "%s array has no %d dimension (max dim. is %d)",	\
		 QUOTE(a), dim, PyArray_NDIM(a));			\
    return rt_error;							\
  }									\
  if (PyArray_DIM(a, dim) != expected_length) {				\
    PyErr_Format(PyExc_ValueError,					\
		 "%s array has wrong %d-dimension=%d (expected %d)",	\
		 QUOTE(a), dim, PyArray_DIM(a, dim), expected_length);	\
    return rt_error;							\
  }
#define TYPE_CHECK(a, tp, rt_error)					\
  if (PyArray_TYPE(a) != tp) {						\
    PyErr_Format(PyExc_TypeError,					\
		 "%s array is not of correct type (%d)", QUOTE(a), tp); \
    return rt_error;							\
  }
#define CALLABLE_CHECK(func, rt_error)				\
  if (!PyCallable_Check(func)) {				\
    PyErr_Format(PyExc_TypeError,				\
		 "%s is not a callable function", QUOTE(func)); \
    return rt_error;						\
  }

#define DIND1(a, i) *((double *) PyArray_GETPTR1(a, i))
#define DIND2(a, i, j) *((double *) PyArray_GETPTR2(a, i, j))
#define DIND3(a, i, j, k) *((double *) Py_Array_GETPTR3(a, i, j, k))

#define IIND1(a, i) *((int *) PyArray_GETPTR1(a, i))
#define IIND2(a, i, j) *((int *) PyArray_GETPTR2(a, i, j))
#define IIND3(a, i, j, k) *((int *) Py_Array_GETPTR3(a, i, j, k))


#define DEF_PYARRAY_GETTER(funcname, selftype, valname)	\
  static PyObject *					\
  funcname(selftype *self, void *closure)		\
  {							\
    Py_INCREF(self->valname);				\
    return PyArray_Return(self->valname);		\
  }
#define DEF_PYARRAY_SETTER(funcname, selftype, valname, arraydim)	\
  static int								\
  funcname(selftype *self, PyObject *value, void *closure)		\
  {									\
    if (value == NULL) {						\
      PyErr_SetString( PyExc_TypeError,					\
		       "Cannot delete the last attribute");		\
      return -1;							\
    }									\
    if ( PyArray_Check(value) != 1 ){					\
      PyErr_Format( PyExc_ValueError,					\
		    "value is not of type numpy array");		\
      return -1;							\
    }									\
    if ( PyArray_NDIM(value) != arraydim ){				\
      PyErr_Format( PyExc_ValueError,					\
		    "value array's dimension %d != arraydim",		\
		    PyArray_NDIM(value));				\
      return -1;							\
    }									\
    if ( PyArray_TYPE(value) != NPY_DOUBLE ){				\
      PyErr_Format( PyExc_ValueError,					\
		    "value array is not of type 'Python float'");	\
      return -1;							\
    }									\
    Py_DECREF(self->valname);						\
    Py_INCREF(value);							\
    self->valname = (PyArrayObject *) value;				\
    return 0;								\
  }

/* ========================================================== DTLSys struct */
typedef struct {
  PyObject_HEAD
  PyArrayObject *wt;
  PyArrayObject *bs;
  PyArrayObject *xt;
} DTLSys;

/* ============================================================ Declaration */
static void       DTLSys_dealloc(DTLSys* self);
static PyObject * DTLSys_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static int        DTLSys_init(DTLSys *self, PyObject *args, PyObject *kwds);

static PyMemberDef DTLSys_members[] = {
    {NULL}  /* Sentinel */
};

static PyObject * DTLSys_get_wt(DTLSys *self,                  void *closure);
static int        DTLSys_set_wt(DTLSys *self, PyObject *value, void *closure);
static PyObject * DTLSys_get_bs(DTLSys *self,                  void *closure);
static int        DTLSys_set_bs(DTLSys *self, PyObject *value, void *closure);
static PyObject * DTLSys_get_xt(DTLSys *self,                  void *closure);
static int        DTLSys_set_xt(DTLSys *self, PyObject *value, void *closure);

static PyGetSetDef DTLSys_getseters[] = {
    {"wt", (getter)DTLSys_get_wt, (setter)DTLSys_set_wt, "Matrix", NULL},
    {"bs", (getter)DTLSys_get_bs, (setter)DTLSys_set_bs, "Vector", NULL},
    {"xt", (getter)DTLSys_get_xt, (setter)DTLSys_set_xt, "Vector time sequence", NULL},
    {NULL}  /* Sentinel */
};

static int       _DTLSys_check_sys_conf(DTLSys *self);
static PyObject * DTLSys_check_sys_conf(DTLSys *self);
static PyObject * DTLSys_make_tms(DTLSys *self, PyObject *args);

static PyMethodDef DTLSys_methods[] = {
  {"check_sys_conf", (PyCFunction)DTLSys_check_sys_conf, METH_NOARGS, "Check if system config is correct"},
  {"make_tms", (PyCFunction)DTLSys_make_tms, METH_VARARGS, "Make TiMe Series"},
  {NULL}  /* Sentinel */
};

static PyTypeObject DTLSysType = {
    PyObject_HEAD_INIT(NULL)
    0,				/*ob_size*/
    "dtls.DTLSys",		/*tp_name*/
    sizeof(DTLSys),             /*tp_basicsize*/
    0,				/*tp_itemsize*/
    (destructor)DTLSys_dealloc, /*tp_dealloc*/
    0,				/*tp_print*/
    0,				/*tp_getattr*/
    0,				/*tp_setattr*/
    0,				/*tp_compare*/
    0,				/*tp_repr*/
    0,				/*tp_as_number*/
    0,				/*tp_as_sequence*/
    0,				/*tp_as_mapping*/
    0,				/*tp_hash */
    0,				/*tp_call*/
    0,				/*tp_str*/
    0,				/*tp_getattro*/
    0,				/*tp_setattro*/
    0,				/*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,	/*tp_flags*/
    "DTLSys objects",           /* tp_doc */
    0,				/* tp_traverse */
    0,				/* tp_clear */
    0,				/* tp_richcompare */
    0,				/* tp_weaklistoffset */
    0,				/* tp_iter */
    0,				/* tp_iternext */
    DTLSys_methods,             /* tp_methods */
    DTLSys_members,             /* tp_members */
    DTLSys_getseters,           /* tp_getset */
    0,				/* tp_base */
    0,				/* tp_dict */
    0,				/* tp_descr_get */
    0,				/* tp_descr_set */
    0,				/* tp_dictoffset */
    (initproc)DTLSys_init,      /* tp_init */
    0,				/* tp_alloc */
    DTLSys_new,                 /* tp_new */
};

static PyMethodDef module_methods[] = {
    {NULL}  /* Sentinel */
};

#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initdtls(void) 
{
  PyObject* m;
  if (PyType_Ready(&DTLSysType) < 0){ return; }

  m = Py_InitModule3("dtls", module_methods,
		     "Example module that creates an extension type.");
  if (m == NULL){ return; }

  Py_INCREF(&DTLSysType);
  PyModule_AddObject(m, "DTLSys", (PyObject *)&DTLSysType);
  import_array();   /* required NumPy initialization */
}

/* ================================================================= Define */
static void
DTLSys_dealloc(DTLSys* self)
{
  Py_XDECREF(self->wt);
  Py_XDECREF(self->bs);
  Py_XDECREF(self->xt);
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
DTLSys_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  DTLSys *self;
  npy_intp wt_dims[2] = {0,0};
  npy_intp bs_dims[1] = {0};
  npy_intp xt_dims[2] = {0,0};

  self = (DTLSys *)type->tp_alloc(type, 0);
  if (self != NULL) {
    self->wt = (PyArrayObject *) PyArray_SimpleNew(2, wt_dims, NPY_DOUBLE);
    if (self->wt == NULL){ Py_DECREF(self); return NULL; }
    self->bs = (PyArrayObject *) PyArray_SimpleNew(1, bs_dims, NPY_DOUBLE);
    if (self->bs == NULL){ Py_DECREF(self); return NULL; }
    self->xt = (PyArrayObject *) PyArray_SimpleNew(2, xt_dims, NPY_DOUBLE);
    if (self->xt == NULL){ Py_DECREF(self); return NULL; }
  }

  return (PyObject *)self;
}

static int
DTLSys_init(DTLSys *self, PyObject *args, PyObject *kwds)
{
  PyArrayObject *wt, *bs, *tmp;
  int t_max;
  npy_intp xt_dims[2] = {0,0};

  if ( !PyArg_ParseTuple( args, "O!O!i:DTLSys.init",
			  &PyArray_Type, &wt,
			  &PyArray_Type, &bs,
			  &t_max)
       ) {
    return -1; /* PyArg_ParseTuple has raised an exception */
  } 
  if ( wt==NULL || bs==NULL ) {
    printf("getting args failed\n"); return -1;
  }
  if ( t_max < 0 ) {
    printf("t_max (3rd arg) must be positive int\n"); return -1;
  }

  xt_dims[0] = PyArray_DIM(wt,0);
  xt_dims[1] = t_max;
  self->xt = (PyArrayObject *) PyArray_SimpleNew(2, xt_dims, NPY_DOUBLE);
  if (self->xt == NULL){ 
    printf("creating %dx%d array failed\n", (int)xt_dims[0], (int)xt_dims[1]);
    return -1;
  }

  tmp = self->wt; Py_INCREF(wt); self->wt = wt; Py_DECREF(tmp);
  tmp = self->bs; Py_INCREF(bs); self->bs = bs; Py_DECREF(tmp);

  if( _DTLSys_check_sys_conf(self) != 0 ){
    PyErr_Clear();
    printf("DTLSys config is not correct!\n");
  }
  return 0;
}

DEF_PYARRAY_GETTER( DTLSys_get_wt, DTLSys, wt )
DEF_PYARRAY_SETTER( DTLSys_set_wt, DTLSys, wt, 2 )
DEF_PYARRAY_GETTER( DTLSys_get_bs, DTLSys, bs )
DEF_PYARRAY_SETTER( DTLSys_set_bs, DTLSys, bs, 1 )
DEF_PYARRAY_GETTER( DTLSys_get_xt, DTLSys, xt )
DEF_PYARRAY_SETTER( DTLSys_set_xt, DTLSys, xt, 2 )

static int
_DTLSys_check_sys_conf(DTLSys *self)
{
  int vecsize;

  NDIM_CHECK(self->wt, 2, -1); TYPE_CHECK(self->wt, NPY_DOUBLE, -1);
  NDIM_CHECK(self->bs, 1, -1); TYPE_CHECK(self->bs, NPY_DOUBLE, -1);

  vecsize = PyArray_DIM(self->wt,0);
  if (vecsize != PyArray_DIM(self->wt,1) ) {
    PyErr_Format( PyExc_ValueError, "self.wt must be square");
    return -1;
  }
  if (vecsize != PyArray_DIM(self->bs,0) ) {
    PyErr_Format( PyExc_ValueError, "self.bs and self.wt[0] must be same shape");
    return -1;
  }
  if (vecsize != PyArray_DIM(self->xt,0) ) {
    PyErr_Format( PyExc_ValueError, "self.xt[,0] and self.wt[0] must be same shape");
    return -1;
  }
  return 0;
}

static PyObject *
DTLSys_check_sys_conf(DTLSys *self)
{
  if( _DTLSys_check_sys_conf(self) != 0 ){
    PyErr_Clear();
    Py_RETURN_FALSE;
  }
  Py_RETURN_TRUE;
}

static PyObject *
DTLSys_make_tms(DTLSys *self, PyObject *args)
{
  int vecsize, t_max, i, j, t;
  if( _DTLSys_check_sys_conf(self) != 0 ){
    return NULL;
  }
  vecsize = PyArray_DIM(self->wt,0);
  t_max   = PyArray_DIM(self->xt,1);

  for (t = 1; t < t_max; t++) {
    for (i = 0; i < vecsize; i++) {
      DIND2(self->xt,i,t) = DIND1(self->bs,i);
      for (j = 0; j < vecsize; j++) {
	DIND2(self->xt,i,t) += DIND2(self->wt,i,j) * DIND2(self->xt,j,t-1);
      }
    }
  }
  return Py_BuildValue("");  /* return None */
}

/*
# setup.py
# build command : python setup.py build build_ext --inplace
from numpy.distutils.core import setup, Extension
import os, numpy

name = 'dtls'
sources = ['dtlsmodule.c']

include_dirs = [
    numpy.get_include()
    ]

setup( name = name,
       include_dirs = include_dirs,
       ext_modules = [Extension(name, sources)]
       )
*/

/*
# test code
import scipy, pylab
import dtls

t_max = 200
rot = 5.0 * 2.0 * scipy.pi / t_max
wt = scipy.array([
    [  scipy.cos(rot), scipy.sin(rot) ],
    [ -scipy.sin(rot), scipy.cos(rot) ]
    ])
wt *= 0.99
bs = scipy.array([0.,0.])

a=dtls.DTLSys( wt, bs, t_max )
a.xt[0,0] = 0
a.xt[1,0] = 1
a.make_tms()

pylab.clf()
pylab.plot(a.xt[0],a.xt[1], 'o-')

# Check calculation
print (scipy.dot( a.wt, a.xt[:,0] ) + a.bs) - a.xt[:,1]
*/

C 用于python扩展模块的C API

==> sonmodule.h <==
typedef struct {
  PyObject_HEAD
  PyObject *str;
  int num;
} Son;

#define MAKE_SON_NEW(self, type, rt_error)	\
  (self) = (Son *)(type)->tp_alloc((type), 0);	\
  if ((self) == rt_error) { return rt_error; }	\
						\
  (self)->str = PyString_FromString("");	\
  if ((self)->str == rt_error) {		\
    Py_DECREF((self));				\
    return rt_error;				\
  }						\
						\
  (self)->num = 0

#ifdef __SON_MODULE
/* ---------- inclue form sonmodule.c ---------- */
static PyTypeObject SonType;

#else
/* ---------- inclue form othere module to use api ---------- */
/* store all api here */
void **Son_API;
/* set alias for easy call */
#define SonType (*(PyTypeObject *)Son_API[0])
#define Son_info (*(PyObject *(*) (Son *))Son_API[1])

static int _import_son(void)
{
  PyObject *son = PyImport_ImportModule("son");
  PyObject *c_api = NULL;
  if (son == NULL){ return -1; }

  /* load c api */
  c_api = PyObject_GetAttrString(son, "_Son_API");
  if (c_api == NULL) {Py_DECREF(son); return -1;}
  if (PyCObject_Check(c_api)) {
    Son_API = (void **)PyCObject_AsVoidPtr(c_api);
  }
  Py_DECREF(c_api);
  Py_DECREF(son);
  if (Son_API == NULL) return -1;

  return 0;
}

#define import_son()				\
  {						\
    if (_import_son() < 0) {			\
      PyErr_Print();				\
      PyErr_SetString( PyExc_ImportError,	\
		       "son failed to import");	\
      return;					\
    }						\
  }

#endif
/* __SONMODULE */

==> sonmodule.c <==
#include <Python.h>
#include "structmember.h"

#define __SON_MODULE
#include "sonmodule.h"
#undef __SON_MODULE

static void
Son_dealloc(Son* self)
{
  Py_XDECREF(self->str);
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
Son_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  Son *self;
  MAKE_SON_NEW(self, type, NULL);
  return (PyObject *)self;
}

static int
Son_init(Son *self, PyObject *args, PyObject *kwds)
{
  PyObject *str=NULL, *tmp;

  static char *kwlist[] = {"str", "num", NULL};

  if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Si", kwlist, 
				    &str,
				    &self->num)){
    return -1; 
  }

  if (str) {
    tmp = self->str;
    Py_INCREF(str);
    self->str = str;
    Py_DECREF(tmp);
  }

  return 0;
}

static PyMemberDef Son_members[] = {
  {"num", T_INT, offsetof(Son, num), 0, "Sone num"},
  {NULL}  /* Sentinel */
};

static PyObject *
Son_getstr(Son *self, void *closure)
{
  Py_INCREF(self->str);
  return self->str;
}

static int
Son_setstr(Son *self, PyObject *value, void *closure)
{
  if (value == NULL) {
    PyErr_SetString(PyExc_TypeError, "Cannot delete the str attribute");
    return -1;
  }
  
  if (! PyString_Check(value)) {
    PyErr_SetString(PyExc_TypeError, 
                    "The str attribute value must be a string");
    return -1;
  }
      
  Py_DECREF(self->str);
  Py_INCREF(value);
  self->str = value;    

  return 0;
}

static PyGetSetDef Son_getseters[] = {
  {"str", (getter)Son_getstr, (setter)Son_setstr, "str", NULL},
  {NULL}  /* Sentinel */
};

static PyObject *
Son_info(Son *self)
{
  PyObject *dic = PyDict_New();
  if (dic == NULL) {
    printf("creating dict failed\n");
    return NULL;
  }
  Py_INCREF(self->str);
  PyDict_SetItemString(dic, "str", self->str);
  PyDict_SetItemString(dic, "num", PyLong_FromLong( self->num ));
  return dic;
}

static PyMethodDef Son_methods[] = {
  {"info", (PyCFunction)Son_info, METH_NOARGS, "return info dic"},
  {NULL}  /* Sentinel */
};

static PyTypeObject SonType = {
  PyObject_HEAD_INIT(NULL)
  0,				/*ob_size*/
  "son.Son",			/*tp_name*/
  sizeof(Son),			/*tp_basicsize*/
  0,				/*tp_itemsize*/
  (destructor)Son_dealloc,	/*tp_dealloc*/
  0,				/*tp_print*/
  0,				/*tp_getattr*/
  0,				/*tp_setattr*/
  0,				/*tp_compare*/
  0,				/*tp_repr*/
  0,				/*tp_as_number*/
  0,				/*tp_as_sequence*/
  0,				/*tp_as_mapping*/
  0,				/*tp_hash */
  0,				/*tp_call*/
  0,				/*tp_str*/
  0,				/*tp_getattro*/
  0,				/*tp_setattro*/
  0,				/*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,	/*tp_flags*/
  "Son objects",		/* tp_doc */
  0,				/* tp_traverse */
  0,				/* tp_clear */
  0,				/* tp_richcompare */
  0,				/* tp_weaklistoffset */
  0,				/* tp_iter */
  0,				/* tp_iternext */
  Son_methods,			/* tp_methods */
  Son_members,			/* tp_members */
  Son_getseters,		/* tp_getset */
  0,				/* tp_base */
  0,				/* tp_dict */
  0,				/* tp_descr_get */
  0,				/* tp_descr_set */
  0,				/* tp_dictoffset */
  (initproc)Son_init,		/* tp_init */
  0,				/* tp_alloc */
  Son_new,			/* tp_new */
};

static PyMethodDef module_methods[] = {
  {NULL}  /* Sentinel */
};

/* ---------- insert object into api array ---------- */
void *Son_API[] = {
  (void *) &SonType,
  (void *) Son_info,
};

#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initson(void) 
{
  PyObject *m, *d;
  PyObject *c_api;
  if (PyType_Ready(&SonType) < 0){ return; }

  m = Py_InitModule3("son", module_methods,
		     "Son Class");

  if (m == NULL){ goto err; }

  Py_INCREF(&SonType);
  PyModule_AddObject(m, "Son", (PyObject *)&SonType);
  
  /* ----- set api to module ----- */
  d = PyModule_GetDict(m);
  if (!d){ goto err; }

  c_api = PyCObject_FromVoidPtr((void *)Son_API, NULL);
  if (c_api == NULL){ goto err; }
  PyDict_SetItemString(d, "_Son_API", c_api);
  Py_DECREF(c_api);

  return;

 err:
  if (!PyErr_Occurred()) {
    PyErr_SetString(PyExc_RuntimeError,
		    "cannot load son module.");
  }
  return;
}

==> fathermodule.c <==
#include <Python.h>
#include "structmember.h"

#include "sonmodule.h"

typedef struct {
  PyObject_HEAD
  Son *son;
} Father;

static void
Father_dealloc(Father* self)
{
  Py_XDECREF(self->son);
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
Father_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  Father *self;

  self = (Father *)type->tp_alloc(type, 0);
  if (self == NULL) { return NULL; }

  MAKE_SON_NEW(self->son, &SonType, NULL);

  return (PyObject *)self;
}

static int
Father_init(Father *self, PyObject *args, PyObject *kwds)
{
  return 0;
}

static PyMemberDef Father_members[] = {
  {NULL}  /* Sentinel */
};

static PyObject *
Father_getson(Father *self, void *closure)
{
  Py_INCREF(self->son);
  return (PyObject *)self->son;
}

static int
Father_setson(Father *self, PyObject *value, void *closure)
{
  if (value == NULL) {
    PyErr_SetString(PyExc_TypeError, "Cannot delete the son attribute");
    return -1;
  }

  if (! PyObject_TypeCheck(value, &SonType)) {/* SonType is from Son_API! */
    PyErr_SetString(PyExc_TypeError, 
                    "The str attribute value must be a Son");
    return -1;
  }

  Py_DECREF(self->son);
  Py_INCREF(value);
  self->son = (Son *)value;

  return 0;
}

static PyGetSetDef Father_getseters[] = {
  {"son", (getter)Father_getson, (setter)Father_setson, "son", NULL},
  {NULL}  /* Sentinel */
};

static PyObject *
Father_info(Father *self)
{
  PyObject *dic = PyDict_New();
  if (dic == NULL) {
    printf("creating dict failed\n");
    return NULL;
  }
  PyDict_SetItemString(dic, "son",
		       Son_info(self->son));/* Son_info is from Son_API! */
  return dic;
}

static PyMethodDef Father_methods[] = {
  {"info", (PyCFunction)Father_info, METH_NOARGS, "return info dic"},
  {NULL}  /* Sentinel */
};

static PyTypeObject FatherType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "father.Father",             /*tp_name*/
    sizeof(Father),             /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)Father_dealloc, /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "Father objects",           /* tp_doc */
    0,		               /* tp_traverse */
    0,		               /* tp_clear */
    0,		               /* tp_richcompare */
    0,		               /* tp_weaklistoffset */
    0,		               /* tp_iter */
    0,		               /* tp_iternext */
    Father_methods,             /* tp_methods */
    Father_members,             /* tp_members */
    Father_getseters,           /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)Father_init,      /* tp_init */
    0,                         /* tp_alloc */
    Father_new,                 /* tp_new */
};

static PyMethodDef module_methods[] = {
    {NULL}  /* Sentinel */
};

#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initfather(void) 
{
  PyObject* m;
  if (PyType_Ready(&FatherType) < 0){ return; }

  m = Py_InitModule3("father", module_methods,
		     "Father Class");

  if (m == NULL){ return; }

  Py_INCREF(&FatherType);
  PyModule_AddObject(m, "Father", (PyObject *)&FatherType);

  import_son();
}

==> setup.py <==
# python setup.py build build_ext --inplace
import sys
import os
from distutils.core import setup, Extension

son_module = Extension(
    'son',
    define_macros = [],
    include_dirs = [],
    libraries = [],
    library_dirs = [],
    extra_compile_args = [],
    sources = ['sonmodule.c'])

father_module = Extension(
    'father',
    define_macros = [],
    include_dirs = [],
    libraries = [],
    library_dirs = [],
    extra_compile_args = [],
    sources = ['fathermodule.c'])

setup(
    name = 'storage',
    version = '1.0',
    description = '',
    ext_modules = [son_module, father_module] )

==> test.txt <==
>>> import son
>>> sn = son.Son()
>>> import father
>>> fr = father.Father()
>>> sn.num = 12
>>> sn.str = "son str"
>>> sn.info()
{'num': 12L, 'str': 'son str'}
>>> fr.son
<son.Son object at 0xb7cd5070>
>>> fr.son.info()
{'num': 0L, 'str': ''}
>>> fr.info()
{'son': {'num': 0L, 'str': ''}}
>>> fr.son = sn
>>> fr.info()
{'son': {'num': 12L, 'str': 'son str'}}

C 在目录上操作

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
//coded by cobra90nj
int main(int argc, char **argv) {

struct dirent *drs;
struct stat buf;

DIR *dir;

	if (argc == 1) {
		dir = opendir(".");
	}
	else {
		dir = opendir(argv[1]);
	}
	
	while ((drs = readdir(dir)) != NULL) {
		stat(drs->d_name, &buf);
		printf("\033[0;20;31m Nome File: %s\n Ultima modifica: %s\n Dimensione file: %d B \n", drs->d_name, ctime(&(buf.st_mtime)), buf.st_size);
	}
	
closedir(dir);

}

C C #define宏使用预处理器中的连接运算符生成注释

#define _AT_ ;/ ## /

C 心跳

#include <avr/io.h>
#include <util/delay.h>

// Some macros that make the code more readable
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin) 

#define LON	1
#define LOF	0

#define LED_COUNT	12

uint8_t led_table[] = 
{
	LOF, PB0, PB1,
	LOF, PB1, PB0,
	LOF, PB0, PB2,
	LOF, PB2, PB0,
	LOF, PB0, PB4,
	LOF, PB4, PB0,
	LOF, PB1, PB2,
	LOF, PB2, PB1,
	LOF, PB1, PB4,
	LOF, PB4, PB1,
	LOF, PB2, PB4,
	LOF, PB4, PB2
};

void clear_leds()
{
	set_input(DDRB, PB0);
	set_input(DDRB, PB1);
	set_input(DDRB, PB2);
	set_input(DDRB, PB4);
}

void set_led(uint8_t index, uint8_t state)
{
	uint8_t i = (index * 3);

	uint8_t s  = led_table[i];
	uint8_t p1 = led_table[i + 1];
	uint8_t p2 = led_table[i + 2];

	set_output(DDRB, p1);  
	set_output(DDRB, p2);

	if(state == LON)
	{
		output_low(PORTB, p1);
		output_high(PORTB, p2);
	}
	else
	{
		output_low(PORTB, p1);
		output_low(PORTB, p2);
	}
}

void delay_10us(uint8_t us)
{
	uint8_t delay_count = F_CPU / 2000000;
   	volatile uint8_t i;
 
   	while (us != 0) {
    	for (i=0; i != delay_count; i++);
     		us--;
   	}
 }
 
void do_pwm_fade(uint8_t index, uint8_t start_duty, uint8_t end_duty, uint8_t rate) 
{
	uint8_t duty;
   	uint8_t j;
 
   	duty = start_duty;
   	while (duty != end_duty) 
	{
    	for (j = 0; j < rate; j++) 
		{
       		set_led(index, LON);
       		delay_10us(duty);
       		set_led(index, LOF);
       		delay_10us(255-duty);
     	}

     	if (start_duty < end_duty) 
       		duty++;
		else 
       		duty--;
	}
}

int main(void) 
{
	// initialize the direction of the B port to be outputs
	// on the 3 pins that have LEDs connected
			
	while(1)
	{
		for(int i=0; i < LED_COUNT; i++)
		{
			clear_leds();
			do_pwm_fade(i, 0, 255, 1);
			do_pwm_fade(i, 255, 0, 1);
		}
	}
}

C Makefile para SRGP

CC = gcc
 
GCCFLAGS = -fpcc-struct-return
CFLAGS = -g
 
INCLUDE = -I/usr/include/srgp
 
LDLIBS =  -lsrgp -lX11 -lm
LDFLAGS = -L/usr/lib
 
$(PROG):
	$(CC) $(GCCFLAGS) $(INCLUDE) $(CFLAGS) $(PROG).c $(LDFLAGS) $(LDLIBS) -o $(PROG)

C tetris.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <SDL/SDL.h>		
#include <SDL/SDL_gfx.h>

#include "io.c"

#define WAIT_TIME 	700 //miliseconds
#define	PIECE_SIZE	5 //in blocks
#define	MAP_HEIGHT	20 // in blocks
#define	MAP_WIDTH	10 // in blocks
#define	MAP_POSITION	320 //px
#define	BLOCK_SIZE	16 //px
#define	MAP_LINE_WIDTH	5 //px

int current_x = 0, current_y = 0;
int piece [PIECE_SIZE] [PIECE_SIZE] = {0};
int map [MAP_WIDTH] [MAP_HEIGHT] = {0};

#define TYPES 2
int pieces [ TYPES ][PIECE_SIZE][PIECE_SIZE] = {
	{
		{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{0, 1, 2, 1, 0},
	 	{0, 0, 1, 0, 0},
		{0, 0, 0, 0, 0}
	}, {
		{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{0, 1, 2, 1, 0},
		{0, 0, 0, 1, 0},
		{0, 0, 0, 0, 0}
	}
};

int i, j; /* VaeRY BAD. */
int screen_height = get_screen_height(); /* BAD. */

unsigned long time_1;
unsigned long time_2;


/* -----------------------  IS_GAME_OVER  ---------------------------------- */
/* If the first line has blocks, then, game over. */

int is_game_over()
{
	for ( i = 0; i < MAP_WIDTH; i++ )
		if ( map[i][0] )
			return 1;
	return 0;
}


/* -----------------------  STORE_PIECE  ----------------------------------- */
/* Store each !=0 block of the piece into the board. */

void store_piece ()
{
	int i1, i2, j1, j2;
	for ( i1 = current_x, i2 = 0; i1 < current_x + PIECE_SIZE; i1++, i2++)
		for ( j1 = current_y, j2 = 0; j1 < current_y + PIECE_SIZE; j1++, j2++)
			if ( piece[j2][i2] )
				map[i1][j1] = 1;
}



/* -----------------------  DELETE_LINE  ----------------------------------- */
/* Delete a line of the board by moving all above lines down */
/*  pY:	Vertical position in blocks of the line to delete */

void delete_line (int y)
{
	for ( j = y; j > 0; j--)
		for ( i = 0; i < MAP_WIDTH; i++)
			map[i][j] = map[i][j-1];
}


/* -----------------------  DELETE_POSSIBLE_LINES  ------------------------- */
/* Delete all the lines that should be removed. */

void delete_possible_lines ()
{
	for ( j = 0; j < MAP_HEIGHT; j++) {
		for ( i = 0; i < MAP_WIDTH; i++ ) {
			if (map[i][j] != 1)
				break;
			i++;
		}
		if ( i == MAP_WIDTH )
			DeleteLine(j);
	}
}



/* -----------------------  IS_POSSIBLE_MOVEMENT  -------------------------- */

int is_possible_movement ( )
{
	int i1, i2, j1, j2;

	for ( i1 = current_x, i2 = 0; i1 < current_x + PIECE_SIZE; i1++, i2++)
		for ( j1 = current_y, j2 = 0; j1 < current_y + PIECE_SIZE; j1++, j2++) {
			/* Check limits */
			if ( i1 < 0 || i1 > MAP_WIDTH - 1 || j1 > MAP_HEIGHT - 1 )
				if ( piece[j2][i2] )
					return 0;

			/* Check collisions with a block already stored in the map. */
			if (j1 >= 0)
				if ( piece[j2][i2] && !map[i1][j1] )
					return 0;
		}
	return 1; /* No collision. Movement IS possible. */
}


/* ------------------------  ROTATE_PIECE  --------------------------------- */

void rotate_piece ()
{
	int piece_2 [PIECE_SIZE] [PIECE_SIZE] = {0};

	for ( i = 0; i < PIECE_SIZE; i++ )
		for ( j = 0; j < PIECE_SIZE; j++ )
			piece_2[i][j] = piece[i][j];
	for ( i = 0; i < PIECE_SIZE; i++ )
		for ( j = 0; j < PIECE_SIZE; j++ )
			piece[i][j] = piece_2[j][i];
}


/* ------------------------  CREATE_NEW_PIECE  ----------------------------- */
void create_new_piece()
{
	for( i = 0; i < PIECE_SIZE; i++ )
		for( j = 0; j < PIECE_SIZE; j++ )
			piece[i][j] = pieces [rand(TYPES)] [i] [j];

	/* ADD function that puts piece in right position. */
	current_y = 0; 		/* TODO */
	current_x = MAP_WIDTH / 2;

	/* may be some rotation...*/
	/* + generate next(). later. */
}


/* ------------------------  DRAW_SHADOW  ---------------------------------- */
void draw_shadow()
{
	/* TODO. 2 */
}


/* ------------------------  DRAW_NEXT_PIECE  ------------------------------ */
void draw_next_piece()
{
	/* TODO. 1 */
}


/* ------------------------  ADD_RUBBISH_TO_MAP  --------------------------- */
void add_rubbish_to_map()
{
	/* TODO. later. */
}


/* -----------------------  DRAW_PIECE  ------------------------------------ */

void draw_piece ()
{
	color piece_color;	/* Color of the block. */

	/* Obtain the position in pixel in the screen of the block we want to draw. */
	int mPixelsY = (screen_height - (BLOCK_SIZE * MAP_HEIGHT)) + (current_y * BLOCK_SIZE);
	int mPixelsX =  ( MAP_POSITION - (BLOCK_SIZE * (MAP_WIDTH / 2)) ) + (current_x * BLOCK_SIZE);


	/* Travel the matrix of blocks of the piece and draw the blocks that are filled. */
	for ( i = 0; i < PIECE_SIZE; i++ )
		for ( j = 0; j < PIECE_SIZE; j++ ) {
			switch ( piece[j][i] ) {
				case 1: 	piece_color = GREEN; break;	/* For each block (except the pivot). */
				case 2: 	piece_color = BLUE;  break;	/* For the pivot. */
				default:	piece_color = YELLOW;break;
			}
			if ( piece[j][i] )
				draw_rectangle ( 
					mPixelsX + i * BLOCK_SIZE,
					mPixelsY + j * BLOCK_SIZE,
					(mPixelsX + i * BLOCK_SIZE) + BLOCK_SIZE - 1,
					(mPixelsY + j * BLOCK_SIZE) + BLOCK_SIZE - 1,
					piece_color );
		}
}


/* -----------------------  DRAW_MAP  -------------------------------------- */

void draw_map ()
{
	/* Calculate the limits of the board in pixels. */
	int X1 = MAP_POSITION - (BLOCK_SIZE * (MAP_WIDTH / 2)) - 1;
	int X2 = MAP_POSITION + (BLOCK_SIZE * (MAP_WIDTH / 2));
	int Y = screen_height - (BLOCK_SIZE * MAP_HEIGHT);

	/* Rectangles that delimits the board. */
	draw_rectangle ( X1 - BOARD_LINE_WIDTH, Y, X1, screen_height - 1, BLUE);
	draw_rectangle ( X2, Y, X2 + BOARD_LINE_WIDTH, screen_height - 1, BLUE);

	/* Drawing the blocks that are already stored in the board. */
	X1++;
	for ( i = 0; i < MAP_WIDTH; i++ )
		for ( j = 0; j < MAP_HEIGHT; j++ )
			if ( map(i, j) )
				draw_rectangle ( 
					X1 + i * BLOCK_SIZE,
					Y + j * BLOCK_SIZE,
					(X1 + i * BLOCK_SIZE) + BLOCK_SIZE - 1,
					(Y + j * BLOCK_SIZE)  + BLOCK_SIZE - 1,
					RED );
}


/* -----------------------  MAIN  ------------------------------------------ */

int main()
{
	add_rubbish_to_map(); /* TODO */
	
	create_new_piece(); /* First piece. */
	/* Get the actual clock milliseconds. */
	time_1 = SDL_GetTicks();

/* ----- Main Loop --------------------------------------------------------- */
	while ( !is_key_down(SDLK_ESCAPE) ) {
/* ----- Draw -------------------------------------------------------------- */
		clear_screen ();
		
		draw_map ();
		draw_piece ();
		draw_next_piece (); /* LATER. */
		draw_shadow (); /* TODO */

		update_screen ();	/* Put the graphic context in the screen. */

/* ----- Input ------------------------------------------------------------- */
		int key = poll_key();
		switch (key) {
			case (SDLK_RIGHT):
				current_x++;
				if ( !is_possible_movement() )
					current_x--;
				break;
			case (SDLK_LEFT):
				current_x--;
				if ( ! )
					current_x++;
				break;
#if 0
			case (SDLK_DOWN):
				current_y++;
				if ( !is_possible_movement() )
					current_y--;
				break;
#endif
			case (SDLK_DOWN):
				/* Check collision from up to down. */
				while ( is_possible_movement() )
					current_y++;
				current_y--;
				store_piece ();

				delete_possible_lines ();
				if ( is_game_over()) {
					puts( "GAME OVER" );
					get_key();
					exit(0);
				}
				create_new_piece();
				break;
			case (SDLK_UP):
				rotate_piece();
				if ( !is_possible_movement() ) {
					/* Stupid hack... =( */
					rotate_piece();
					rotate_piece();
					rotate_piece();
				}
				break;
			default:
				puts( "Suka. <, >, A, V." );
				break;
		}

/* ----- Vertical movement ------------------------------------------------- */
		time_2 = SDL_GetTicks();

		if ( (time_2 - time_1) > WAIT_TIME ) {
			current_y++;
			if ( !is_game_over() ) {
				store_piece ();
				delete_possible_lines ();
				if ( is_game_over() ) {
					puts( "GAME OVER" );
					get_key();
					exit(0);
				}
				create_new_piece();
			}
			time_1 = SDL_GetTicks();
		}
	}		/* while ( !is_key_down(SDLK_ESCAPE) ) */
	
	return 0;
}

C 分析文字

#include <stdio.h>
#include <malloc.h>

int main() {
	const int l_block = 1024;

	FILE* input_text_file;
	long n = 0, i = 0, j = 0;
	int meet_comma = 0;
	long file_lengh;
	char* buffer;
	int num_block;


	input_text_file = fopen( "../../additional_files/en.txt", "r" );	
	if ( !input_text_file ) {
		puts( "Can't open file!" );
		return 1;
	}

	fseek( input_text_file, 0, SEEK_END );
	file_lengh = ftell( input_text_file );
	buffer = (char*) malloc(  (file_lengh + 1) * sizeof(char)  );

	num_block = file_lengh / l_block;
	fseek( input_text_file, 0, SEEK_SET );
	fread( buffer, l_block, num_block + 1, input_text_file );
	buffer[file_lengh] = '\0';
	
/* -----------------------------  PROCESSING  ------------------------------ */

	while( buffer[i]) {
		switch ( buffer[i] ) {
			case ',':
				meet_comma = 1;
				break;
			case '.':
			case '!':
			case '?':
				if ( !meet_comma )   /* Если запятой небыло. */
					for ( j = n; j <= i; j++ )
						putchar( buffer[j] );
				meet_comma = 0;
				n = i + 1;
				break;
			default: break;
		}
		i++;
	}

/* ------------------------------------------------------------------------- */

	fclose ( input_text_file );
	free(buffer);
	puts("");

	return 0;
}

C 从文件中加载或保存一块内存

void*loadfile(const char*const s){
 FILE*f=fopen(s,"rb");
 if(f){
  fseek(f,0,SEEK_END);
  {
   const int ml=ftell(f);
   if(ml){
    char*m=malloc(ml);
    if(m){
     rewind(f);
     fread(m,1,ml,f);
     fclose(f);
     return m;
    }
   }
  }
 }
 return 0;
}


int savefile(const char*const s,const void*const m,const int ml){
 FILE*f=fopen(s,"wb");
 if(f){
  int ok=fwrite(m,1,ml,f)==ml;
  fclose(f);
  return ok;
 }
 return 0;
}

C RSA

/* rsa.c */

#include <gmp.h>
#include <stdio.h>
#include <assert.h>

/* проверяет, является ли число простым. Если нет, то делает таковым. */
/* Просто́е число́ это натуральное число, 
которое имеет ровно 2 различных делителя (только 1 и самоё себя). */

void check_for_prime(mpz_ptr p)
{
	int forprimep = mpz_probab_prime_p (p, 50);
	while (forprimep == 0) {
		mpz_add_ui (p, p, 1);
		forprimep = mpz_probab_prime_p (p, 50);
	};
}

const int SIZE = 512; 	/* Размер ключей. */

/* --------------------------------  MAIN  --------------------------------- */
int main (int argc, char* argv[])
{
	mpz_t p, q;

/* Инициализация рандома */
	gmp_randstate_t state;
	gmp_randinit_default(state);

/* 1. Генерируется случайные простые числа p и q */
	mpz_init2(p,SIZE);
	mpz_urandomb(p, state, SIZE);

	check_for_prime(p);

	mpz_init2(q,SIZE);
	mpz_urandomb(q, state, SIZE);

	check_for_prime(q);

	puts("p = ");
	mpz_out_str (stdout, 10, p);
	puts("\nq = ");
	mpz_out_str (stdout, 10, q);

/* 2. Вычисляется их произведение n = pq */
	mpz_t n;
	mpz_init(n);
	mpz_mul(n,p,q);

	puts("\nn = ");
	mpz_out_str (stdout, 10, n);

/* 3. Вычисляется значение функции Эйлера от числа n.

Функция Эйлера  ( phi(n), где n — натуральное число ) 
равна количеству натуральных чисел, не больших n и взаимно простых с ним. */
	mpz_t fi;
	mpz_init(fi);

	mpz_t p_m, q_m;
	mpz_init(p_m);
	mpz_init(q_m);
	mpz_sub_ui(p_m, p, 1);
	mpz_sub_ui(q_m, q, 1);

	mpz_mul(fi, p_m, q_m);

	puts("\nfi = ");
	mpz_out_str (stdout, 10, fi);

/* 4. Выбирается целое число e, взаимно простое со значением функции fi

время выполнения операций растёт с увеличением количества ненулевых 
битов в двоичном представлении открытой экспоненты e. 
Чтобы увеличить скорость шифрования, значение e 
часто выбирают равным 17, 257 или 65537 — простым числам, 
двоичное представление которых содержит лишь две единицы: 
17 = 0x11, 257 = 0x101, 65537 = 0x10001 (простые числа Ферма). */

	int possible_values[] = {
		17, 257, 65537
	};

	mpz_t e;
	mpz_init(e);
	mpz_t gcd;
	mpz_init(gcd);
	int i = 0;
	for (; i < 3; ++i)
	{
		mpz_set_ui(e,possible_values[i]);
		mpz_gcd(gcd, e, fi);
		int compgcd = mpz_cmp_ui(gcd, 1);
		if (compgcd == 0)
			break;
	}
	assert(i != 3); 	/* выбор был сделан */
	puts("\ne = ");
	mpz_out_str (stdout, 10, e);

/* 5. Вычисляется число d мультипликативное обратное к числу e по модулю fi */
	mpz_t d;
	mpz_init(d);

	mpz_invert(d, e, fi);
	puts("\nd = ");
	mpz_out_str (stdout, 10, d);

/* Пара P = (e,n) публикуется в качестве открытого ключа RSA */
/* Пара S = (d,n) играет роль секретного ключа RSA */

/* ------------------------------------------------------------------------- */
/* Цифровая подпись. (Все переменные имеют приставку 's_') */

/* Открытый текст */
/* В качестве текста возьмем рандомное число. Так или иначе, текст 
   необходимо привести к какому-то числу */
	mpz_t s_M;
	mpz_init2(s_M,SIZE / 2);
	mpz_urandomb(s_M, state, SIZE / 2);
	puts("\ns_M = ");
	mpz_out_str (stdout, 10, s_M);

/* Создаем цифровую подпись sigma с помощью своего секретного ключа S */
	mpz_t s_sigma;
	mpz_init(s_sigma);

	mpz_powm(s_sigma, s_M, d, n);
	puts("\ns_sigma = ");
	mpz_out_str (stdout, 10, s_sigma);

/* Проверяем подлинность подписи (Pa должно равняться M) */
	mpz_t s_Pa;
	mpz_init(s_Pa);

	mpz_powm(s_Pa, s_sigma, e, n);
	puts("\ns_Pa = ");
	mpz_out_str (stdout, 10, s_Pa);

	int compgcd = mpz_cmp(s_M, s_Pa);
	if (compgcd == 0) {
		puts("\ns_M == s_Pa");
	}
	else {
		puts("\ns_M != s_Pa");
	}

/* ------------------------------------------------------------------------- */
/* Шифрование. */
	mpz_t M;
	mpz_init2 (M,SIZE / 2);
//	mpz_urandomb (M, state, SIZE / 2);
	mpz_set_ui(M, 11);
	puts ("\nM = ");
	mpz_out_str (stdout, 10, M);

/* Шифрование. */
	mpz_t Pa;
	mpz_init (Pa);

	mpz_powm (Pa, M, e, n);
	puts ("\nPa = ");
	mpz_out_str (stdout, 10, Pa);

/* Дешифрование. */
	mpz_t Sa;
	mpz_init (Sa);

	mpz_powm(Sa, Pa, d, n);
	puts("\nSa = ");
	mpz_out_str (stdout, 10, Sa);

/* Проверка. */
	if (mpz_cmp(M, Sa) == 0) {
		puts("\nM == Sa");
	}
	else {
		puts("\nM != Sa");
	}
	
/* ------------------------------------------------------------------------- */
/* Text encription. */

	int i = 0;


	mpz_t text [32];
	mpz_t Pa_2 [32];
	char text_M[] = "some text.";
	puts("");
	puts("initial text:");
	puts (text_M);
	puts("");

	puts("codes:");
	for ( i=0; text_M [i] != '\0'; i++ ) {
		mpz_init ( Pa_2[i] );
		mpz_init ( text[i] );
		mpz_set_ui ( text[i], text_M[i] );

		mpz_powm ( Pa_2[i], text[i], e, n );
		mpz_out_str ( stdout, 10, Pa_2[i] );
		puts ("");
	}

/* ------------------*/
	mpz_t Sa_2[32];

	puts("");
	puts("result text:");

	for ( i=0; text_M [i] != '\0'; i++ ) {
		mpz_init ( Sa_2[i] );
		mpz_powm ( Sa_2[i], Pa_2[i], d, n );

		putchar ( (char)mpz_get_si(Sa_2[i]) );
	}
/* ------------------*/

	return 0;
}