出于性能原因,我想将部分python程序移植到C++中,因此我尝试为程序编写一个简单的扩展.C++部分将构建一个字典,然后需要将其传递给Python程序.
我发现的一种方法似乎是在C++中构建我的类似dict的对象,例如a boost::unordered_map,然后使用Py_BuildValue[1]方法将其转换为Python ,该方法能够生成Python dicts.但是这种方法包括将容器转换为字符串表示并返回看起来有点太多"即将到来"才能成为最高性能的解决方案!?
所以我的问题是:在C++中构建Python字典的最高效方法是什么?我看到boost有一个Python库,它支持在C++和Python之间映射容器,但到目前为止我没有在文档中找到我需要的东西.如果有这样的方式我宁愿在C++中直接构建Python dict,那么就不需要复制等.但如果最有效的方法是另一种方式,我也很擅长.
这是(简化的)C++ - 我编译成.dll/.pyd的代码:
#include <iostream>
#include <string>
#include <Python.h>
#include "boost/unordered_map.hpp"
#include "boost/foreach.hpp"
extern "C"{
typedef boost::unordered_map<std::string, int> hashmap;
static PyObject*
_rint(PyObject* self, PyObject* args)
{
hashmap my_hashmap; // DO I NEED THIS?
my_hashmap["a"] = 1; // CAN I RATHER INSERT TO PYTHON DICT DIRECTLY??
BOOST_FOREACH(hashmap::value_type i, my_hashmap) {
// INSERT ELEMENT TO PYTHON DICT
}
// return PYTHON DICT
}
static PyMethodDef TestMethods[] = …Run Code Online (Sandbox Code Playgroud) 我已经定义了一个自定义build_ext来构建一个时髦的扩展,我试图使 pip 友好。以下是我正在做的修剪版本。
foo_ext = Extension(
name='foo/_foo',
sources=foo_sources,
)
class MyBuildExt(build_ext):
def build_extension(self, ext):
# This standalone script builds the __init__.py file
# and some .h files for the extension
check_call(['python', 'build_init_file.py'])
# Now that we've created all the init and .h code
# build the C/C++ extension using setuptools/distutils
build_ext.build_extension(self, ext)
# Include the generated __init__.py in the build directory
# which is something like `build/lib.linux-x86/foo/`.
# How can I get setuptools/distutils to install the
# generated …Run Code Online (Sandbox Code Playgroud) 我试图通过从 python 调用 C 文件来传递一个值,然后再次将该值从 C 返回到 python。
我的问题是如何做到这一点?可以使用返回Py_BuildValue(a+b)类型的东西吗?
#include <Python.h>
static PyObject *
hello_world(PyObject *self, PyObject *noargs)
{
int a=5,b=10;
return Py_BuildValue(a+b); //This is Errorus.
}
static PyMethodDef
module_functions[] = {
{ "hello_world", hello_world, METH_NOARGS, "hello world method" },
{ NULL }
};
PyMODINIT_FUNC
inittesty2(void)
{
Py_InitModule("testy2", module_functions);
}
Run Code Online (Sandbox Code Playgroud) 我有一个用于模糊字符串搜索的自定义python模块,实现了Levenshtein距离计算,它包含一个称为levtree的python类型,它具有两个成员,该指针指向执行所有计算的wlevtree C类型(称为tree)的指针和指向的PyObject * python字符串的python列表,称为wordlist。这是我需要的:
-当我创建levtree的新实例时,我使用一个构造函数,该构造函数将字符串元组作为其唯一输入(并且该字典将在其中实例执行所有搜索),该构造函数将必须创建levtree的新实例。将wordlist添加到levtree的新实例中,然后将输入元组的内容复制到wordlist的新实例中。这是我的第一个代码段和第一个问题:
static int
wlevtree_python_init(wlevtree_wlevtree_obj *self, PyObject *args, PyObject *kwds)
{
int numLines; /* how many lines we passed for parsing */
wchar_t** carg; /* argument to pass to the C function*/
unsigned i;
PyObject * strObj; /* one string in the list */
PyObject* intuple;
/* the O! parses for a Python object (listObj) checked
to be of type PyList_Type */
if (!(PyArg_ParseTuple(args, "O!", &PyTuple_Type, &intuple)))
{
return -1;
}
/* get the number of lines …Run Code Online (Sandbox Code Playgroud) 嗨,我正在尝试使用 C++ 中的 swig python 扩展,例如 -在 Mit 页面上
我的标题是-shapes.h
#include <iostream>
class Shape
{
public:
Shape()
{
nshapes++;
}
~Shape()
{
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { };
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public: …Run Code Online (Sandbox Code Playgroud) 我正在使用 SWIG 创建一些我无法更改的 C++ 代码的 Python 接口。其中一个 C++ 类有一个构造函数,该构造函数创建一个尚未使用的部分初始化的对象,必须首先对其调用初始化函数。我想在 Python 中通过提供一个替代构造函数来解决这个问题,该构造函数可以同时完成两件事(获取和初始化)。假设在 C++ 中我有
class X {
public:
X() {...}
void init(T a) {...}
...
};
Run Code Online (Sandbox Code Playgroud)
在 C++ 中,我必须将 X 实例化为
X x;
x.init(a);
Run Code Online (Sandbox Code Playgroud)
在Python中我想做
x = X(a)
Run Code Online (Sandbox Code Playgroud)
我的解决方案是一个 hack,取决于目标语言和 SWIG 生成包装器代码的具体方式:在我的 .i 文件中,我有
%inline %{
X* new_X(T a) {
X* ret = new X();
ret->init(a);
return ret;
}
%nodefaultctor X;
class X {
public:
...
%extend {
%pythoncode {
def __init__(self, *args):
this = _modulename.new_X(*args)
try:
self.this.append(this)
except:
self.this = …Run Code Online (Sandbox Code Playgroud) 我正在为python3.7写一个C扩展模块。我有一个简单的结构作为PyObject:
typedef struct {
PyObject_HEAD
double attacker;
double victim;
double game_hardness;
int inflation;
} RatingSystem;
Run Code Online (Sandbox Code Playgroud)
和初始化器:
static int
RatingSystem_init(RatingSystem *self, PyObject *args, PyObject *kwargs) {
double kek;
static char *kwargs_list[] = {"attacker", "victim", "game_hardness", "inflation"};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$dddi", kwargs_list,
&self->attacker, &self->victim,
&self->game_hardness, &self->inflation)) {
return -1;
}
printf("Success\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我在python 3.7.3下的Mac OS上运行它,一切正常,但是如果我切换到alpine 3.10 python docker image(python:3.7-alpine),请执行以下初始化:
import rating_system
rs = rating_system.RatingSystem(attacker=1000.0, victim=1000.0, game_hardness=1300.0, inflation=1)
Run Code Online (Sandbox Code Playgroud)
我懂了Segmentation fault。在gdb下运行显示以下内容:
Program received signal SIGSEGV, Segmentation fault.
vgetargskeywords (args=0x7f87284f0050, kwargs=0x7f87284e0a00, …Run Code Online (Sandbox Code Playgroud) 我试图在 vs 代码中安装 mypy 扩展,但它一直在下面显示这个错误
C:\Users\Yourusername\Dev\django_project_boilerplate\env\Scripts\python.exe: can't open file 'c:UsersYourusername.vscodeextensionsms-python.python-2020.6.89148pythonFilespyvsc-run-isolated.py': [Errno 2] No such file or directory
(env)
Run Code Online (Sandbox Code Playgroud)
然后我意识到终端正在从下面命令的文件位置中删除反斜杠,因为它是一个特殊字符
c:/Users/Yourusername/Dev/django_project_boilerplate/env/Scripts/python.exe c:\Users\Yourusername\.vscode\extensions\ms-python.python-2020.6.89148\pythonFiles\pyvsc-run-isolated.py pip install -U mypy
Run Code Online (Sandbox Code Playgroud) 我正在构建一个使用“第三方”库的 C Python 扩展——在本例中,我使用单独的构建过程和工具链构建了一个。调用这个库libplumbus.dylib。
目录结构为:
grumbo/
include/
plumbus.h
lib/
libplumbus.so
grumbo.c
setup.py
Run Code Online (Sandbox Code Playgroud)
我的setup.py样子大约是:
from setuptools import Extension, setup
native_module = Extension(
'grumbo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
sources = ['grumbo.c'],
include_dirs = ['include'],
libraries = ['plumbus'],
library_dirs = ['lib'])
setup(
name = 'grumbo',
version = '1.0',
ext_modules = [native_module] )
Run Code Online (Sandbox Code Playgroud)
由于 libplumbus 是一个外部库,当我运行时,import grumbo我得到:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dlopen(/path/to/grumbo/grumbo.cpython-37m-darwin.so, 2): Library not loaded: lib/libplumbus.dylib
Referenced …Run Code Online (Sandbox Code Playgroud) 我正在努力将Python模块移植到Windows.我有一个玩具示例如下.
文件夹结构是:
foo/
libfoo/
foo.c
setup.py
Run Code Online (Sandbox Code Playgroud)
setup.py
from setuptools import setup, Extension
sources = ['libfoo/foo.c']
foo = Extension('libfoo',
sources = sources,
define_macros = None,
include_dirs = ['./libfoo'],
libraries = None,
library_dirs = None,
)
setup(name = 'foo',
ext_modules = [foo],
install_requires = ['setuptools'],
)
Run Code Online (Sandbox Code Playgroud)
libfoo/foo.c(完整性)
#include <stdio.h>
void foo() {
printf("Hello World!");
}
Run Code Online (Sandbox Code Playgroud)
当我尝试安装包时,遇到错误.
C:\Users\user\foo>python setup.py install
running install
running bdist_egg
running egg_info
creating foo.egg-info
writing requirements to foo.egg-info\requires.txt
writing foo.egg-info\PKG-INFO
writing top-level names to foo.egg-info\top_level.txt
writing dependency_links to …Run Code Online (Sandbox Code Playgroud) 我正在.pyd使用Visual Studio 2015 C ++项目和Python 2.7 32位构建Python扩展()。
这是我的.cpp文件:
#include <Python.h>
static PyObject* GetTwoInts(PyObject* self, PyObject* args)
{
srand(time(NULL));
int random1 = rand() % 10;
int random2 = rand() % 10;
PyObject * python_val = Py_BuildValue("ii", random1, random2);
return python_val;
}
static PyObject* GetListTwoInts(PyObject* self, PyObject* args)
{
srand(time(NULL));
int random1 = rand() % 10;
int random2 = rand() % 10;
PyObject *val1 = PyInt_FromLong(random1);
PyObject *val2 = PyInt_FromLong(random2);
PyObject *result = PyList_New(2);
PyList_SetItem(result, 0, val1);
PyList_SetItem(result, …Run Code Online (Sandbox Code Playgroud) 比distutils使用SWIG构建python扩展(xxx.so)更容易 。您无需编写wrap.c程序即可包装原始的c程序。所以我想使用SWIG而不是Distutils。但是没有方法可以通过编写setup.py文件来自动安装扩展名(xxx.so)。这困扰了我很多天。
为了更清楚地解释这个问题,我使用“逐步”策略将其弄清楚。
步骤1?有一个原始的C / C ++代码。然后使用SWIG创建Python包装器。
步骤2:使用Distuils(编写setup.py)或仅使用gcc命令行创建Python扩展文件。Python扩展名是xxx.so。显然,在此步骤中,您可以使用Distuils将编译和安装结合在一起。
步骤3:通过编写setup.py安装xxx.so Python扩展。
我只是不知道STEP 3如何编写setup.py以安装xxx.so Python扩展。
是否可以通过编写setup.py而不使用sys.path.append()或sys.path.insert()方法来安装python扩展(xxx.so)?
非常感谢您提供的任何答案!
最后,我尝试了将编译和安装结合在一起的STEP 2方法。它可以正常工作,但是使用setup.py仅安装_xxx.so Python扩展并不是我的目的。
目录结构:
setup.py
src/
libdemo/
__init__.py
LibHello.py
lib/
palindrome.c # original C code
palindrome_wrap.c # Python wrapper built by SWIG
Run Code Online (Sandbox Code Playgroud)
setup.py代码:
#-*- coding:utf-8 -*-
import sys
import os
from setuptools import setup, find_packages, Extension
libPath = "lib"
moduleLibPalindrome = Extension(
name = 'libdemo._palindrome',
sources = [os.path.join(libPath, 'palindrome_wrap.c'),
os.path.join(libPath, 'palindrome.c')]
)
setup (
name = 'test_example',
version = '0.1',
author = "Hobart", …Run Code Online (Sandbox Code Playgroud) 我有中等的业余技能,Python而且我是初学者,asm并且对C语言没有任何了解.
我知道python C-extensions必须遵循特定的接口才能正常工作.
是否可以Assembly使用正确的界面和完整功能编写纯粹的python扩展?第二个问题是,如果这样做的话,它是否足够有效?
谷歌搜索时,我没有找到任何关于这个问题的代码或一些文章或解决方案的例子.
这不是关于asm从内部运行代码的问题Python所以它不是关于SO的主题的重复.
python ×12
c ×4
c++ ×4
python-c-api ×3
setuptools ×3
swig ×3
alpine-linux ×1
assembly ×1
cpython ×1
dictionary ×1
distutils ×1
docker ×1
linker ×1
performance ×1
pip ×1
sdn ×1
setup.py ×1
terminal ×1
windows ×1