- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
感谢this handy skeleton module,我成功地用C 扩展了python .但是我找不到 C++ 的,并且在尝试修复 C++ 在编译此骨架模块时给出的错误时遇到循环依赖问题。
如何用 C++ 扩展 Python?
如果没有必要,我宁愿不依赖 Boost(或 SWIP 或其他库)。依赖是一个痛苦的屁股。最好的情况是,我找到了一个已经用 C++ 编译的骨架文件。
这是我为 C++ 制作的经过编辑的骨架:
#include <Python.h>
#include "Flp.h"
static PyObject * ErrorObject;
typedef struct {
PyObject_HEAD
PyObject * x_attr; // attributes dictionary
} FlpObject;
static void Flp_dealloc(FlpObject * self);
static PyObject * Flp_getattr(FlpObject * self, char * name);
static int Flp_setattr(FlpObject * self, char * name, PyObject * v);
DL_EXPORT(void) initflp();
static PyTypeObject Flp_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Flp", /*tp_name*/
sizeof(FlpObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Flp_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)Flp_getattr, /*tp_getattr*/
(setattrfunc)Flp_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
#define FlpObject_Check(v) ((v)->ob_type == &Flp_Type)
static FlpObject * newFlpObject(PyObject * arg)
{
FlpObject * self;
self = PyObject_NEW(FlpObject, &Flp_Type);
if (self == NULL)
return NULL;
self->x_attr = NULL;
return self;
}
// Flp methods
static void Flp_dealloc(FlpObject * self)
{
Py_XDECREF(self->x_attr);
PyMem_DEL(self);
}
static PyObject * Flp_demo(FlpObject * self, PyObject * args)
{
if (! PyArg_ParseTuple(args, ""))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef Flp_methods[] = {
{"demo", (PyCFunction)Flp_demo, 1},
{NULL, NULL} // sentinel
};
static PyObject * Flp_getattr(FlpObject * self, char * name)
{
if (self->x_attr != NULL) {
PyObject * v = PyDict_GetItemString(self->x_attr, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
return Py_FindMethod(Flp_methods, (PyObject *)self, name);
}
static int Flp_setattr(FlpObject * self, char * name, PyObject * v)
{
if (self->x_attr == NULL) {
self->x_attr = PyDict_New();
if (self->x_attr == NULL)
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(self->x_attr, name);
if (rv < 0)
PyErr_SetString(PyExc_AttributeError,
"delete non-existing Flp attribute");
return rv;
}
else
return PyDict_SetItemString(self->x_attr, name, v);
}
/* --------------------------------------------------------------------- */
/* Function of two integers returning integer */
static PyObject * flp_foo(PyObject * self, PyObject * args)
{
long i, j;
long res;
if (!PyArg_ParseTuple(args, "ll", &i, &j))
return NULL;
res = i+j; /* flpX Do something here */
return PyInt_FromLong(res);
}
/* Function of no arguments returning new Flp object */
static PyObject * flp_new(PyObject * self, PyObject * args)
{
FlpObject *rv;
if (!PyArg_ParseTuple(args, ""))
return NULL;
rv = newFlpObject(args);
if ( rv == NULL )
return NULL;
return (PyObject *)rv;
}
/* Example with subtle bug from extensions manual ("Thin Ice"). */
static PyObject * flp_bug(PyObject * self, PyObject * args)
{
PyObject *list, *item;
if (!PyArg_ParseTuple(args, "O", &list))
return NULL;
item = PyList_GetItem(list, 0);
/* Py_INCREF(item); */
PyList_SetItem(list, 1, PyInt_FromLong(0L));
PyObject_Print(item, stdout, 0);
printf("\n");
/* Py_DECREF(item); */
Py_INCREF(Py_None);
return Py_None;
}
/* Test bad format character */
static PyObject * flp_roj(PyObject * self, PyObject * args)
{
PyObject *a;
long b;
if (!PyArg_ParseTuple(args, "O#", &a, &b))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/* List of functions defined in the module */
static PyMethodDef flp_methods[] = {
{"roj", flp_roj, 1},
{"foo", flp_foo, 1},
{"new", flp_new, 1},
{"bug", flp_bug, 1},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initflp) */
DL_EXPORT(void) initflp()
{
PyObject *m, *d;
/* Initialize the type of the new type object here; doing it here
* is required for portability to Windows without requiring C++. */
Flp_Type.ob_type = &PyType_Type;
/* Create the module and add the functions */
m = Py_InitModule("flp", flp_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
ErrorObject = PyErr_NewException("flp.error", NULL, NULL);
PyDict_SetItemString(d, "error", ErrorObject);
}
这对我来说编译得很好,但是当我测试它时:
$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import flp
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initflp)
>>>
最佳答案
首先,即使你不想引入额外的依赖,我建议你看看PyCXX .引用其网页:
CXX/Objects is a set of C++ facilities to make it easier to write Python extensions. The chief way in which PyCXX makes it easier to write Python extensions is that it greatly increases the probability that your program will not make a reference-counting error and will not have to continually check error returns from the Python C API. CXX/Objects integrates Python with C++ in these ways:
- C++ exception handling is relied on to detect errors and clean up. In a complicated function this is often a tremendous problem when writing in C. With PyCXX, we let the compiler keep track of what objects need to be dereferenced when an error occurs.
- The Standard Template Library (STL) and its many algorithms plug and play with Python containers such as lists and tuples.
- The optional CXX/Extensions facility allows you to replace the clumsy C tables with objects and method calls that define your modules and extension objects.
我认为 PyCXX 是在 BSD 许可证下获得许可的,这意味着如果您的扩展程序将在类似的许可证下发布,您也可以将 PyCXX 的整个源代码包含在您的扩展程序的分布式压缩包中。
如果你真的绝对不想依赖 PyCXX 或任何其他第三方库,我认为你只需要 wrap Python 解释器将在 extern "C"{
和 }
中调用的函数,以避免名称混淆。
这是更正后的代码:
#include <Python.h>
#include "Flp.h"
static PyObject * ErrorObject;
typedef struct {
PyObject_HEAD
PyObject * x_attr; // attributes dictionary
} FlpObject;
extern "C" {
static void Flp_dealloc(FlpObject * self);
static PyObject * Flp_getattr(FlpObject * self, char * name);
static int Flp_setattr(FlpObject * self, char * name, PyObject * v);
DL_EXPORT(void) initflp();
}
static PyTypeObject Flp_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Flp", /*tp_name*/
sizeof(FlpObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Flp_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)Flp_getattr, /*tp_getattr*/
(setattrfunc)Flp_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
#define FlpObject_Check(v) ((v)->ob_type == &Flp_Type)
static FlpObject * newFlpObject(PyObject * arg)
{
FlpObject * self;
self = PyObject_NEW(FlpObject, &Flp_Type);
if (self == NULL)
return NULL;
self->x_attr = NULL;
return self;
}
// Flp methods
static void Flp_dealloc(FlpObject * self)
{
Py_XDECREF(self->x_attr);
PyMem_DEL(self);
}
static PyObject * Flp_demo(FlpObject * self, PyObject * args)
{
if (! PyArg_ParseTuple(args, ""))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef Flp_methods[] = {
{"demo", (PyCFunction)Flp_demo, 1},
{NULL, NULL} // sentinel
};
static PyObject * Flp_getattr(FlpObject * self, char * name)
{
if (self->x_attr != NULL) {
PyObject * v = PyDict_GetItemString(self->x_attr, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
return Py_FindMethod(Flp_methods, (PyObject *)self, name);
}
static int Flp_setattr(FlpObject * self, char * name, PyObject * v)
{
if (self->x_attr == NULL) {
self->x_attr = PyDict_New();
if (self->x_attr == NULL)
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(self->x_attr, name);
if (rv < 0)
PyErr_SetString(PyExc_AttributeError,
"delete non-existing Flp attribute");
return rv;
}
else
return PyDict_SetItemString(self->x_attr, name, v);
}
/* --------------------------------------------------------------------- */
/* Function of two integers returning integer */
static PyObject * flp_foo(PyObject * self, PyObject * args)
{
long i, j;
long res;
if (!PyArg_ParseTuple(args, "ll", &i, &j))
return NULL;
res = i+j; /* flpX Do something here */
return PyInt_FromLong(res);
}
/* Function of no arguments returning new Flp object */
static PyObject * flp_new(PyObject * self, PyObject * args)
{
FlpObject *rv;
if (!PyArg_ParseTuple(args, ""))
return NULL;
rv = newFlpObject(args);
if ( rv == NULL )
return NULL;
return (PyObject *)rv;
}
/* Example with subtle bug from extensions manual ("Thin Ice"). */
static PyObject * flp_bug(PyObject * self, PyObject * args)
{
PyObject *list, *item;
if (!PyArg_ParseTuple(args, "O", &list))
return NULL;
item = PyList_GetItem(list, 0);
/* Py_INCREF(item); */
PyList_SetItem(list, 1, PyInt_FromLong(0L));
PyObject_Print(item, stdout, 0);
printf("\n");
/* Py_DECREF(item); */
Py_INCREF(Py_None);
return Py_None;
}
/* Test bad format character */
static PyObject * flp_roj(PyObject * self, PyObject * args)
{
PyObject *a;
long b;
if (!PyArg_ParseTuple(args, "O#", &a, &b))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/* List of functions defined in the module */
static PyMethodDef flp_methods[] = {
{"roj", flp_roj, 1},
{"foo", flp_foo, 1},
{"new", flp_new, 1},
{"bug", flp_bug, 1},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initflp) */
DL_EXPORT(void) initflp()
{
PyObject *m, *d;
/* Initialize the type of the new type object here; doing it here
* is required for portability to Windows without requiring C++. */
Flp_Type.ob_type = &PyType_Type;
/* Create the module and add the functions */
m = Py_InitModule("flp", flp_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
ErrorObject = PyErr_NewException("flp.error", NULL, NULL);
PyDict_SetItemString(d, "error", ErrorObject);
}
关于c++ - 如何用 C++ 扩展 python?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2847617/
我是 magento 的新手,目前我在 magento 安装期间遇到“必须加载 PHP 扩展 curl ”错误。你能帮帮我吗? 最佳答案 如果您的服务器上没有安装 curl,您可以键入以下命令之一来安
我在 macOS Mojave/macOS Big Sur/macOS Monterey/macOS Ventura 上使用最新的 php 版本 7.2 并收到类似错误 $composer requ
这个问题已经有答案了: Why generic type is not applicable for argument extends super class for both? (5 个回答) 已关
我正在使用 NightWatch.js 并进行一些 UI 测试,我想用一些额外的 desiredCapabilities 启动默认浏览器实例(即启用扩展并应用一些特定值)。 p> 注意:我可以执行这些
有人知道为什么我在 java 8 中使用此代码时没有服务器扩展名称吗: try { URL url = new URL(urlString); URLC
扩展提供给我的类(class)。为现有的类提供新功能。或扩展现有的mixin s 或虚拟类,任何东西都可以工作。 也许是这样的: class FlatButton {} // maybe no
我有一个关于使用 c 代码和 mod_wsgi 扩展 python 的问题。 我在 apache 服务器中有一个 django 应用程序,它查询 postgresql 数据库以生成报告。在某些报告中,
testcafe支持在Chrome浏览器中加载crx扩展吗? 如果是这样,请告诉我需要尝试什么方法。 我尝试了下面的代码,但没有成功 await t.eval(new Function(fs.read
这个问题已经有答案了: What is a raw type and why shouldn't we use it? (16 个回答) 已关闭 3 年前。 有什么区别: // 1 class A c
我正在编写一个 chrome 扩展来记录单击开始按钮后触发的请求。 这是我的文件:1. list .json { "manifest_version": 2, "name": "recorde
我每天都在使用 vim 和 perforce 现在我的问题是,如果我想查看 perforce 文件修订版,则从命令模式下的 vim :!p4 打印文件#1 vim 试图让我获得缓冲区 #1。有没有办法
大家好,我有一个关于 NUnit 扩展(2.5.10)的问题。 我想做的是向 数据库。为此,我使用 Event 创建了 NUnit 扩展 听众。 我遇到的问题是公共(public)无效 TestFin
我有弹出窗口,而不是模态窗口。 如何通过单击页面的其他部分(不在窗口中)来关闭此窗口? 最佳答案 像这样的东西: function closeWin(e, t) { var el = win.
我通常非常谨慎地使用扩展方法。当我确实觉得有必要编写一个扩展方法时,有时我想重载该方法。我的问题是,您对调用其他扩展方法的扩展方法有何看法?不好的做法?感觉不对,但我无法真正定义原因。 例如,第二个
扩展 Ant Ant带有一组预定义的任务,但是你可以创建自己的任务,如下面的例子所示。 定制Ant 任务应扩展 org.apache.tools.ant.Task 类,同时也应该拓展 execut
我想要一个重定向所有请求的扩展: http://website.com/foo.js 到: http://localhost/myfoo.js 我无法使用主机文件将主机从 website.com 编辑
对于为什么 QChartView 放在 QTabWidget 中时会扩展,我有点迷惑。 这是 QChartView 未展开(因为它被隐藏)时应用程序的图片。 应用程序的黑色部分是 QOpenGLWid
如果在连接条件中使用 OR 运算符,如何优化以下查询以避免 SQL 调优方面的 OR 扩展? SELECT t1.A, t2.B, t1.C, t1.D, t2.E FROM t1 LEFT J
一旦加载插件的问题得到解决(在 .NET 中通过 MEF 的情况下),下一步要解决的是与它们的通信。简单的方法是实现一个接口(interface),使用插件实现,但有时插件只需要扩展应用程序的工作方式
在我的 Symfony2 包中,我需要检查是否定义了一个函数(一个扩展)。更具体地说,如果安装了 KnpMenuBundle,我会在我的包中使用那个,否则我将自己渲染插件。 我试过了,但这当然不起作用
我是一名优秀的程序员,十分优秀!