C 中的 Python 实例方法

发布于 2024-08-15 19:33:14 字数 355 浏览 1 评论 0原文

考虑以下 Python (3.x) 代码:

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

如何用 C 编写相同的功能?

我的意思是,如何使用 C 中的方法创建对象?然后从中创建一个实例?

编辑: 哦,对不起!我的意思是通过 Python C API 实现相同的功能。如何通过 Python 的 C API 创建方法? 像这样的东西:

PyObject *Foo = ?????;
PyMethod??? *bar = ????;

Consider the following Python (3.x) code:

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

How to write the same functionality in C?

I mean, how do I create an object with a method in C? And then create an instance from it?

Edit:
Oh, sorry! I meant the same functionality via Python C API. How to create a Python method via its C API?
Something like:

PyObject *Foo = ?????;
PyMethod??? *bar = ????;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

稚然 2024-08-22 19:33:14

这是一个简单的类(改编自 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;
}

Here's a simple class (adapted from http://nedbatchelder.com/text/whirlext.html for 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;
}
差↓一点笑了 2024-08-22 19:33:14

你不能! 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();

You can't! C does not have "classes", it only has structs. And a struct cannot have code (methods or functions).

You can, however, fake it with function pointers:

/* 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();
或十年 2024-08-22 19:33:14

我建议您从示例源代码开始 这里 -- 它是 Python 3 源代码的一部分,它的存在是专门为了通过示例向您展示如何执行您所需要的操作(以及除此之外的其他一些事情) -- 使用 C API 来创建一个模块,在该模块中创建一个新类型,为该类型赋予方法和属性。这基本上是源代码的第一部分,最终是 Xxo_Type 的定义——然后您将获得如何定义各种函数、您可能不关心的其他一些类型的示例,最后是模块对象本身及其初始化(当然,您可以跳过大部分内容,但不能跳过模块对象及其导致定义感兴趣类型的初始化部分;-)。

在学习和调整源代码以满足您的特定需求时,您可能遇到的大多数问题在 文档,尤其是部分关于“对象实现支持”——但是当然,您总是可以在这里提出一个新问题(每个问题一个问题最好——一个包含许多实际问题的“问题”总是很麻烦!-)准确地显示您正在做的事情、您期望的结果以及您所看到的结果——您将得到的答案往往包括一些非常有用的答案;-)。

I suggest you start from the example source code here -- it's part of Python 3's sources, and it exists specifically to show you, by example, how to perform what you require (and a few other things besides) -- use the C API to create a module, make a new type in that module, endow that type with methods and attributes. That's basically the first part of the source, culminating in the definition of Xxo_Type -- then you get examples of how to define various kinds of functions, some other types you may not care about, and finally the module object proper and its initialization (you can skip most of that of course, though not the module object and the parts of its initialization that lead up to the definition of the type of interest;-).

Most of the questions you might have while studying and adapting that source to your specific needs have good answers in the docs, especially in the section on "Object Implementation Support" -- but of course you can always open a new question here (one per issue would be best -- a "question" with many actual questions is always a bother!-) showing exactly what you're doing, what you were expecting as a result, and what you are seeing instead -- and you'll get answers which tend to include some pretty useful ones;-).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文