سؤال

النظر في رمز Python (3.x) التالي:

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

كيف تكتب نفس الوظيفة في ج؟

أعني ، كيف يمكنني إنشاء كائن بطريقة في C؟ ثم إنشاء مثيل منه؟

تعديل: أه آسف! قصدت نفس الوظيفة عبر Python C API. كيفية إنشاء طريقة Python عبر C API؟ شيء مثل:

PyObject *Foo = ?????;
PyMethod??? *bar = ????;
هل كانت مفيدة؟

المحلول

إليك فئة بسيطة (مقتبسة من http://nedbatchelder.com/text/whirlext.html لـ 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;
}

نصائح أخرى

لا يمكنك! لا يحتوي C على "فصول" ، بل لديها فقط structس. و struct لا يمكن أن يكون لها رمز (طرق أو وظائف).

ومع ذلك ، يمكنك مزيفها مع مؤشرات الوظائف:

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

أقترح عليك أن تبدأ من رمز المصدر المثال هنا - إنه جزء من مصادر Python 3 ، وهي موجودة على وجه التحديد لتظهر لك ، على سبيل المثال ، كيفية أداء ما تحتاجه (وعدد قليل من الأشياء الأخرى إلى جانب)- استخدم C API لإنشاء وحدة نمطية ، وجعل نوعًا جديدًا في تلك الوحدة ، تمنح هذا النوع مع الطرق والسمات. هذا هو في الأساس الجزء الأول من المصدر ، وبلغت ذروتها في تعريف Xxo_Type - ثم تحصل على أمثلة على كيفية تحديد أنواع مختلفة من الوظائف ، وبعض الأنواع الأخرى التي قد لا تهتم بها ، وأخيراً كائن الوحدة النمطية بشكل صحيح وتهيئة (يمكنك تخطي معظم ذلك بالطبع ، على الرغم من أنه ليس كائن الوحدة ونظامه أجزاء من التهيئة التي تؤدي إلى تعريف نوع الاهتمام ؛-).

معظم الأسئلة التي قد تكون لديك أثناء دراسة وتكييف هذا المصدر مع احتياجاتك المحددة لها إجابات جيدة في المستندات, ، خاصة في الجزء على "دعم تنفيذ الكائن" - ولكن بالطبع يمكنك دائمًا فتح سؤال جديد هنا (سيكون أحدهما أفضل - "سؤال" مع العديد من الفعلي أسئلة دائمًا ما يكون ذلك بمثابة عناء!-) إظهار ما تفعله بالضبط ، وما كنت تتوقعه نتيجة لذلك ، وما تراه بدلاً من ذلك-وستحصل على إجابات تميل إلى تضمين بعض الإجازة المفيدة ؛-).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top