我想在我的宠物项目中嵌入一些python.我已将问题减少到以下代码:
#include <Python.h>
#include "iostream"
int main(int argc, char *argv[])
{
Py_Initialize();
PyObject *globals = Py_BuildValue("{}");
PyObject *locals = Py_BuildValue("{}");
PyObject *string_result = PyRun_StringFlags(
"a=5\n"
"s='hello'\n"
"d=dict()\n"
,
Py_file_input, globals, locals, NULL);
if ( PyErr_Occurred() ) {PyErr_Print();PyErr_Clear();return 1;}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(我知道我没有清理任何参考文献.这是一个例子.)
它可以编译
c++ $(python-config --includes) $(python-config --libs) test.cpp -o test
Run Code Online (Sandbox Code Playgroud)
如果我运行它,我会收到以下错误:
$ ./test
Traceback (most recent call last):
File "<string>", line 3, in <module>
NameError: name 'dict' is not defined
Run Code Online (Sandbox Code Playgroud)
看来内置函数没有加载.我也import什么都没有.我明白了__import__.如何加载丢失的模块或我遗漏的任何内容?
谢谢.
我有一个本地库,其自然界面将涉及传递可能大的数字.我预计大约一半是<32位; 另一季度<64位; 接下来的第八个<128位 - 依此类推,没有固定的长度限制.
如果我可以约束值以适合单个寄存器,那么PyLong_FromUnsignedLongLong()和PyLong_AsUnsignedLongLong()将是合适的.
PyLong_FromString()克服了这一点 - 但需要中间表示的不必要的代价._PyLong_FromByteArray()和_PyLong_AsByteArray()减轻了这个成本(通过简化这个中间表示),但是前导下划线让我想知道这是否会导致可移植性问题.
在longintrepr.h中,我发现了struct _longobject ...它暗示它可能是一种直接与内部表示交互的方式......虽然没有关于这种结构的详细文档仍然是一个障碍.
什么方法将导致Python和库之间的最佳吞吐量?有没有我忽略过的文件?
我正在努力将python嵌入到c ++中.在某些特殊情况下,我需要在同一个线程中有两个独立的解释器实例.
我可以将Python解释器包装到c ++类中并从两个或更多类实例中获取服务吗?
[更新:问题解决了!见帖子的底部]
我需要允许python开发人员将打包数据数组(在本例中为顶点)传递给我的API,这是一系列通过Python C API手动公开的C++接口.我对此的初步印象是使用ctypes Structure类来允许这样的接口:
class Vertex(Structure):
_fields_ = [
('x', c_float),
('y', c_float),
('z', c_float),
('u', c_float),
('v', c_float),
('color', c_int)
]
verts = (Vertex * 3)()
verts[0] = Vertex(0.0, 0.5, 0.0, 0.0, 0.5, 0xFF0000FF)
verts[1] = Vertex(0.5, -0.5, 0.0, 0.5, -0.5, 0x00FF00FF)
verts[2] = Vertex(-0.5, -0.5, 0.0, -0.5, -0.5, 0x0000FFFF)
device.ReadVertices(verts, 3) # This is the interfaces to the C++ object
Run Code Online (Sandbox Code Playgroud)
我试图传递的函数具有以下签名:
void Device::ReadVertices(Vertex* verts, int count);
Run Code Online (Sandbox Code Playgroud)
Python包装器看起来像这样:
static PyObject* Device_ReadVertices(Py_Device* self, PyObject* args)
{
PyObject* py_verts;
int …Run Code Online (Sandbox Code Playgroud) python文档说,cPickle比Pickle更快的原因是,前者是用C实现的.这究竟是什么意思?
我正在使用Python制作高级数学模块,有些计算需要花费大量时间.这是否意味着如果我的程序在C中实现,它可以更快?
我想从其他Python程序导入这个模块,就像我可以导入cPickle一样.
你能解释一下如何在C中实现Python模块吗?
我有一个动态链接到Python解释器的C++应用程序.我希望能够从特定目录导入python模块.我想修改我的进程的PYTHONPATH,以便sys.path将包含我添加到PYTHONPATH的路径.根据这个文档,这似乎是它的工作方式:
http://docs.python.org/c-api/intro.html#embedding-python
但是,当我从Python-land打印sys.path时,它具有PYTHONPATH的原始内容而不是我设置的内容.这是我正在做的一个例子(使用Boost.Python):
int main(int argc, char* argv[])
{
_putenv_s("PYTHONPATH", "C:\\source\\\\modules");
Py_Initialize();
object main = import("__main__");
object global = (main.attr("__dict__"));
exec("import sys\nprint sys.path"), global, global);
}
Run Code Online (Sandbox Code Playgroud)
PS - 我知道还有其他方法可以实现我的目标,但这不是我所要求的.我想知道为什么Py_Initialize()在设置sys.path时不使用PYTHONPATH的当前值.或许我误解了它应该如何运作?
我有一个wx.py.Shell.shell小部件,它允许用户执行与我的程序交互的python代码.我希望能够将用户在此空间中定义的函数传递给我的C++代码(通过wxswig生成的自定义小部件包装器)并执行它.
在我的C++代码中,我使用std :: function <>类来调用绑定函数(C++或Python)
所以我创建了一个简单的类来用函数调用操作符包装PyObject.但是当我尝试调用PyObject*时,我得到了一个段错误.
class PyMenuCallback
{
PyObject *Func;
public:
PyMenuCallback(const PyMenuCallback &op2);
PyMenuCallback(PyObject *func);
~PyMenuCallback ();
void operator() (int id);
};
/////////////////////////////////////////////////////////
PyMenuCallback::PyMenuCallback(PyObject *func)
: Func(func)
{
Py_XINCREF (Func);
if(!PyCallable_Check(Func))
cout << "Not a Callable Callback." << endl; //Throw an exception or something
}
PyMenuCallback::PyMenuCallback(const PyMenuCallback &op2)
: Func (op2.Func)
{
Py_XINCREF (Func);
if(!PyCallable_Check(Func))
cout << "Not a Callable Callback." << endl;
}
PyMenuCallback::~PyMenuCallback()
{
Py_XDECREF (Func);
}
void PyMenuCallback::operator() (int id)
{
cout << "Calling Callback" …Run Code Online (Sandbox Code Playgroud) 我正在扩展我们的库(支持Python 2.7)中的类以支持PEP 3118,后者已经被反向移植到2.7.
从文档中,我需要初始化tp_as_buffer字段以指向a PyBufferProcs.但是,从2.7的文档中,此结构的描述仅包含旧缓冲区协议的条目.从来源,我收集的是
PyBufferProcs对新协议(一些其他的项目bf_getbuffer和bf_releasebuffer).
问题仍然存在:
我是否必须做一些特别的事情来告诉Python这些新条目是否有效?
我是否必须填写旧协议的条目?(例如,2.7的文档说明bf_getsegcount
可能不为空.但如果我支持PEP 3118,则不应使用此条目.)
要学习如何创建C扩展,我决定只复制一个内置.c文件(在本例中itertoolsmodule.c)并将其放在我的包中.我只能从更改的名称在模块内部itertools来mypkg.
然后我编译它(Windows 10,MSVC Community 14)setuptools.Extension:
from setuptools import setup, Extension
itertools_module = Extension('mypkg.itertoolscopy',
sources=['src/itertoolsmodulecopy.c'])
setup(...
ext_modules=[itertools_module])
Run Code Online (Sandbox Code Playgroud)
默认使用编译器标志/c /nologo /Ox /W3 /GL /DNDEBUG /MD,我在某处读取这些默认值等于python编译方式的设置.但是我使用conda(64位设置),所以这可能不一定是真的.
这一切都进展顺利 - 但是一个基准测试filterfalse显示它几乎比内置的慢2倍:
import mypkg
import itertools
import random
a = [random.random() for _ in range(500000)]
func = None
%timeit list(filter(func, a))
100 loops, best of 3: 3.42 ms per loop
%timeit list(itertools.filterfalse(func, a))
100 loops, best of 3: 3.41 ms …Run Code Online (Sandbox Code Playgroud) 我正在尝试安装位于已安装目录中的 Python(C 扩展,如果重要的话)包,出于安全原因,该包是只读的。但是,默认情况下,pip 会在其自己位置调用的子目录中构建包build,但我不能这样做。
$ pip install /mnt/remote/pkgname
Processing /mnt/remote/pkgname
Preparing metadata (setup.py) ... done
Using legacy 'setup.py install' for pkgname, since package 'wheel' is not installed.
Installing collected packages: pkgname
Attempting uninstall: pkgname
Found existing installation: pkgname 1.0.0
Uninstalling pkgname-1.0.0:
Successfully uninstalled pkgname-1.0.0
Running setup.py install for pkgname ... error
ERROR: Command errored out with exit status 1:
command: /path/to/venv/bin/python3.8 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/mnt/remote/pkgname/setup.py'"'"'; __file__='"'"'/mnt/remote/pkgname/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if …Run Code Online (Sandbox Code Playgroud) python ×10
python-c-api ×10
c++ ×3
python-3.x ×2
boost-python ×1
c ×1
pep3118 ×1
performance ×1
pip ×1
pybuffer ×1
python-2.7 ×1
structure ×1
swig ×1
wxpython ×1