Frage

Sie sich den folgenden Python (3.x) Code:

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

Wie die gleiche Funktionalität in C schreiben?

Ich meine, wie erstelle ich ein Objekt mit einer Methode in C? Und dann eine Instanz davon erstellen?

Bearbeiten : Oh, Entschuldigung! Ich wollte die gleiche Funktionalität über Python-C-API. Wie eine Python-Methode über seinen C-API erstellen? So etwas wie:

PyObject *Foo = ?????;
PyMethod??? *bar = ????;
War es hilfreich?

Lösung

Hier ist eine einfache Klasse (angepasst von http://nedbatchelder.com/text/whirlext.html für 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;
}

Andere Tipps

Sie können nicht! C hat keine „Klassen“, es hat nur structs. Und ein struct kann nicht Code (Methoden oder Funktionen) hat.

Sie können jedoch gefälschtes es mit Funktionszeigern:

/* 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();

Ich schlage vor, Sie aus dem Beispielquellcode starten hier - es ist ein Teil von Python 3 der Quellen, und es speziell Sie, durch Beispiel zu zeigen, besteht, wie man durchführen, was Sie benötigen (und ein paar andere Dinge außer) - verwenden Sie die C-API erzeugen ein Modul, einen neuen Typ in diesem Modul machen, diese Art mit Methoden und Attribute verleihen. Das ist im Grunde der erste Teil der Quelle, in der Definition von Xxo_Type gipfelt - dann Sie Beispiele davon, wie verschiedene Arten von Funktionen zu definieren, einige andere Arten nicht zu können kümmern, und schließlich das Modulobjekt richtige und seine Initialisierung (Sie die meisten davon natürlich überspringen kann, wenn auch nicht das Modulobjekt und die Teile seiner Initialisierung, die zur Definition der Art von Interesse hinführen; -).

Die meisten Fragen haben Sie vielleicht während des Studiums und die Anpassung dieser Quelle auf Ihre speziellen Bedürfnisse haben gute Antworten in die Dokumentation , vor allem im Abschnitt auf „Object Implementation Support“ - aber natürlich kann man immer hier eine neue Frage offen (eine pro Ausgabe am besten wäre - eine „Frage“ mit vielen tatsächlichen Fragen ist immer die Mühe ! -) zeigt genau das, was Sie tun, was Sie als Ergebnis erwartet hatten, und was Sie sehen statt - und Sie werden Antworten ein paar ziemlich nützlichen schließen neigen zu erhalten, die; -).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top