更改 C++/Python 代码中的参数值
changing argument value in a C++/Python code
我的问题如下:我有一个C++代码,我无法随心所欲地修改(不是我编写的,并且在某些知识产权限制下)。我必须通过 Python main 将其与 Python 代码链接。我使用boost::p ython进行反射。在代码中的某个时刻,C++函数使用 C++ 函数的 Python 重载函数来修改参数。这个函数在 Python 中使用时效果很好。但是当由 C++ 函数调用时,在返回C++时不会考虑参数的修改。为了对问题进行建模,我编写了一个简化版本,旨在隔离我的问题。
以下是C++类:
#include <iostream>
using namespace std;
#include <boost/ref.hpp>
//Class aimed at modeling a C++ user's type that should be used in Python
class C
{
public:
double myC;
C(){}
~C(){}
void setValue(double val) {
myC = val;
}
double getValue() {
return myC;
}
};
/*
This class will be derived in Python
We want to be sure that:
- void (g) and non void (f) functions are properly reflected and extended in Python
- a function (h) with a local type (C) will properly use the python overloaded function of a C++ function (g)
*/
class A
{
public:
A(){int A_x=0;}
virtual ~A(){}
virtual int f(int Ivar){
Ivar = 0;
return Ivar;
}
virtual void g(C * myC){
C calledC;
cout << "I should not be here" << endl; //When B::setparam call g, it should be the Python g, not the virtual function from base class
calledC.setValue(0.);
//return *myC;
}
C h(){ //This function wont be overloaded in Python
C myC;
//myC.setValue(0.);
this->g(&myC); //We want myC to be modified, and the python overloaded version of g to be used
cout << "Value back in C++: " << myC.getValue() << endl; //We want to verify if myC has been modified back in C++
return myC;
}
};
/*
This class will be called from a main in Python.
It's function setparam is aimed at ensuring that Python extension of a C++ class is supported properly
*/
class B
{
public:
B(A & a){
setparam(a);
}
B(){
int u;
u = 0;
}
virtual ~B(){}
void setparam(A & a){
a.h(); //Here the code should call the h overloaded function of the derived class of A in Python
}
};
提升::p ython 包装器:
#include <boost/python.hpp>
#include <Python.h>
#include <object.h>
#include "ClassA.h"
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <iostream>
using namespace std;
using namespace boost::python;
/*
A wrapper is used to allow overload of virtual A function
*/
struct WrapperClassA : A, boost::python::wrapper<A>{
int f(int Ivar){
if(override f = this->get_override("f")){
return f(Ivar);
}
else {
return A::f(Ivar);
}
}
int default_f(int Ivar){
return this->A::f(Ivar);
}
void g(C * myC){
if(override g = this->get_override("g")){
g(myC);
}
else {
A::g(myC);
}
}
void default_g(C * myC){
this->A::g(myC);
}
};
/*
Refection of necessary classes and functions for Python
*/
BOOST_PYTHON_MODULE(myWrapper){
class_<WrapperClassA, boost::noncopyable>("A", init<>())
.def("f", &A::f, &WrapperClassA::default_f)
.def("g", &A::g, &WrapperClassA::default_g)
;
class_<B, boost::noncopyable>("B", init<>())
.def("setparam", &B::setparam)
;
class_<C>("C", init<>())
.def("setValue", &C::setValue)
.def("getValue", &C::getValue)
.def_readwrite("myC", &C::myC)
;
}
蟒蛇代码:
from math import *
# C++ library
from myWrapper import *
"""
Extension of C++ class A
APy should be used when A type argument is called
g should be able to use a C++ C type object and to modify it
The constructor call g in order to verify that myC is treated as mutable within Python
"""
class APy(A):
def __init__(self):
A.__init__(self)
n = 0
x = 0.
myC = C()
self.g(myC)
print("value after a 1st call within Python: " + repr(myC.getValue()))
def f(self, n):
n = 5
return n
def g(self, myC):
x = 7.0
myC.setValue(x)
print("value in Python: " + repr(myC.getValue()))
"""
Main
myB.setparam should be able to pass a APy argument
"""
myA = APy()
myB = B()
myB.setparam(myA)
当我运行代码时,print("value in Python: " + repr(myC.getValue())) print 7,但 cout <<myC.getValue() <<endl print 0,而我希望变量在 7。感谢您的任何帮助。
这里的问题是,当你在调用g(myC)
中将C
实例转换为Python时,Boost.Python使用按值转换器而不是浅值转换器(即它复制C
实例),即使你传递了一个指针。
这是设计使然:当你将C++指针传递给Python时,Boost.Python希望确保Python代码不必担心其他C++代码删除它,而Python层仍然可以访问它,因为这可能会导致危险的内存错误。 确保这一点的唯一方法是复制对象。
如果你想强制 Boost.Python 通过引用传递myC
对象,请使用 g(boost::python::ptr(myC))
(如果你知道它不是空的,g(boost::ref(*myC))
),但请注意这是危险的;你需要确保 g()
的 Python 实现不会试图在其生命周期之后保留其参数。
您可以在此处找到更多信息:
http://www.boost.org/doc/libs/1_48_0/libs/python/doc/v2/callbacks.html
您还可以使用 boost::shared_ptr
将参数传递给 Python,而无需以安全的方式进行复制:
提升 Python:如何调用C++虚函数
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 根据编译时参数在 C 中重复代码
- 扩展C++生成的代码的模板参数类型名称
- 将函数作为参数传递以避免重复代码
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++基于输入参数的动态代码生成
- 调用参数不是原子参数的函数是此代码引发异常的原因吗?
- 引入参数化构造函数后显示 LNK 2019 未解析外部符号的代码错误
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- C++17.处理使用 auto 相关的模板参数.代码排序困难
- 为什么EclipseCDT代码格式化程序有时会在模板参数中引入空格
- 我写了一个类,它总是将其函数参数委托给它的成员,我该如何改进代码
- 编译器是否C++具有相同模板参数集的每个模板类实例生成代码?
- 如何将char数组声明为函数参数?或告诉我此代码中还有其他问题?
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- 如何基于构造函数参数模板化类成员函数的代码
- 在存在错误代码的情况下输出参数与 NRVO
- 在完美转发函数中公开参数类型,避免代码重复
- 中断长代码 snprintf 格式和参数
- 使用 const double* const 作为模板参数 - 代码性能问题