Question

Considérez le code Python (3.x) suivant:

class Foo(object):
    def bar(self):
        pass
foo = Foo()

Comment écrire les mêmes fonctionnalités en C?

Je veux dire, comment puis-je créer un objet avec une méthode en C? Et puis créer une instance de celui-ci?

Modifier : Oh pardon! Je voulais dire la même fonctionnalité via l'API Python C. Comment créer une méthode Python via son API C? Quelque chose comme:

PyObject *Foo = ?????;
PyMethod??? *bar = ????;
Était-ce utile?

La solution

Voici une classe simple (adapté de http://nedbatchelder.com/text/whirlext.html pour 3.x):

#include "Python.h"
#include "structmember.h"

// The CountDict type.

typedef struct {
   PyObject_HEAD
   PyObject * dict;
   int count;
} CountDict;

static int
CountDict_init(CountDict *self, PyObject *args, PyObject *kwds)
{
   self->dict = PyDict_New();
   self->count = 0;
   return 0;
}

static void
CountDict_dealloc(CountDict *self)
{
   Py_XDECREF(self->dict);
   self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
CountDict_set(CountDict *self, PyObject *args)
{
   const char *key;
   PyObject *value;

   if (!PyArg_ParseTuple(args, "sO:set", &key, &value)) {
      return NULL;
   }

   if (PyDict_SetItemString(self->dict, key, value) < 0) {
      return NULL;
   }

   self->count++;

   return Py_BuildValue("i", self->count);
}

static PyMemberDef
CountDict_members[] = {
   { "dict",   T_OBJECT, offsetof(CountDict, dict), 0,
               "The dictionary of values collected so far." },

   { "count",  T_INT,    offsetof(CountDict, count), 0,
               "The number of times set() has been called." },

   { NULL }
};

static PyMethodDef
CountDict_methods[] = {
   { "set",    (PyCFunction) CountDict_set, METH_VARARGS,
               "Set a key and increment the count." },
   // typically there would be more here...

   { NULL }
};

static PyTypeObject
CountDictType = {
   PyObject_HEAD_INIT(NULL)
   0,                         /* ob_size */
   "CountDict",               /* tp_name */
   sizeof(CountDict),         /* tp_basicsize */
   0,                         /* tp_itemsize */
   (destructor)CountDict_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*/
   "CountDict object",        /* tp_doc */
   0,                         /* tp_traverse */
   0,                         /* tp_clear */
   0,                         /* tp_richcompare */
   0,                         /* tp_weaklistoffset */
   0,                         /* tp_iter */
   0,                         /* tp_iternext */
   CountDict_methods,         /* tp_methods */
   CountDict_members,         /* tp_members */
   0,                         /* tp_getset */
   0,                         /* tp_base */
   0,                         /* tp_dict */
   0,                         /* tp_descr_get */
   0,                         /* tp_descr_set */
   0,                         /* tp_dictoffset */
   (initproc)CountDict_init,  /* tp_init */
   0,                         /* tp_alloc */
   0,                         /* tp_new */
};

// Module definition

static PyModuleDef
moduledef = {
    PyModuleDef_HEAD_INIT,
    "countdict",
    MODULE_DOC,
    -1,
    NULL,       /* methods */
    NULL,
    NULL,       /* traverse */
    NULL,       /* clear */
    NULL
};


PyObject *
PyInit_countdict(void)
{
    PyObject * mod = PyModule_Create(&moduledef);
    if (mod == NULL) {
        return NULL;
    }

    CountDictType.tp_new = PyType_GenericNew;
    if (PyType_Ready(&CountDictType) < 0) {
        Py_DECREF(mod);
        return NULL;
    }

    Py_INCREF(&CountDictType);
    PyModule_AddObject(mod, "CountDict", (PyObject *)&CountDictType);

    return mod;
}

Autres conseils

Vous ne pouvez pas! C ne pas « classes », il n'a que structs. Et un struct ne peut pas avoir le code (méthodes ou fonctions).

Vous pouvez, cependant, faux avec des pointeurs de fonction:

/* struct object has 1 member, namely a pointer to a function */
struct object {
    int (*class)(void);
};

/* create a variable of type `struct object` and call it `new` */
struct object new;
/* make its `class` member point to the `rand()` function */
new.class = rand;

/* now call the "object method" */
new.class();

Je vous suggère de commencer à partir du code source exemple ici - cela fait partie des sources de Python 3, et il existe spécifiquement pour vous montrer, par exemple, comment effectuer ce que vous avez besoin (et quelques autres choses encore) - utiliser l'API C créer un module, faire un nouveau type dans ce module, doter ce type avec des méthodes et des attributs. C'est essentiellement la première partie de la source, aboutissant à la définition de Xxo_Type - alors vous obtenez des exemples de la façon de définir différents types de fonctions, d'autres types que vous ne se soucient pas, et enfin l'objet du module approprié et son initialisation (vous peut ignorer la plupart de ce bien sûr, mais pas l'objet du module et les parties de son initialisation qui mènent à la définition du type d'intérêt; -).

La plupart des questions que vous pourriez avoir en étudiant et en adaptant cette source à vos besoins spécifiques ont de bonnes réponses dans les docs , en particulier dans la section sur « l'objet de soutien de mise en œuvre » - mais bien sûr vous pouvez toujours ouvrir une nouvelle question ici (une par question serait mieux - une « question » avec de nombreux réels questions est toujours la peine ! -) montrant exactement ce que vous faites, ce que vous attendiez en conséquence, et ce que vous voyez à la place - et vous aurez des réponses qui ont tendance à inclure certains assez utiles, les -.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top