Boost Python 2:使用 `std::string &` 的构造函数
Boost Python 2: Constructors using `std::string &`
我有一个 C++ 遗留代码(编辑起来会很痛苦),出于速度原因,我需要在 Python 2 中使用它。
我有两个类。一个负责从内存中加载大量数据,形式为std::string
,并将其转换为内部表示MiddleClass
。第二个是将其从内部表示 MiddleClass
转换回 std::string
.
class Load {
Load(const std::string & data) { ... };
MiddleClass load() { ... };
};
class Save {
Save(std::string & data) { .... };
void save(const MiddleClass & middleclass) { ... };
};
我的目标是,在 Python 2 中使用此设置,如下所示:
import datahandler # my lib
import requests
request = request.get("url-to-data")
loader = datahandler.Load(request.content) # my C++ class Load
internal_representation = loader.load()
.
.
.
result_variable = str() # or None or something not important
saver = datahandler.Save(result_variable) # my C++ class Save
saver.save(internal_representation)
我怎样才能做到这一点?
我 运行 从一开始就遇到了麻烦。
简单变体:
BOOST_PYTHON_MODULE(datahandler)
{
class_<MiddleClass>("MiddleClass");\
// some .defs - not important
class <Load>("Load", init<const std::string &>())
.def("load". &Load::load);
class <Save>("Save", init<std::string &>())
.def("save". &Save::save);
}
可以编译,不用担心,但是加载的数据不知何故被破坏了,这让我想到,我做的非常错误。
我还发现了 this 有点跑题的 SO 问题,它告诉我,我不能有 std::string &
,因为 Python 字符串是不可变的。
所以结论:我不知道现在该怎么办:(这里有人能帮我吗?谢谢。
参考这个工作示例。
- 定义你的 C++ 类。例如:
class MiddleClass {
public:
explicit MiddleClass(const std::string& data) : parent_data_(data) {}
void print() {
std::cout << parent_data_ << std::endl;
}
private:
std::string parent_data_;
};
class Loader {
public:
explicit Loader(const std::string& data) :
data_(data){
};
MiddleClass load() {
return MiddleClass(data_);
};
private:
std::string data_;
};
- 创建增强绑定
boost::python::class_<MiddleClass>("MiddleClass",
boost::python::init<const std::string&>(boost::python::arg("data"), ""))
.def("print_data", &MiddleClass::print);
boost::python::class_<Loader>("Loader",
boost::python::init<const std::string&>(boost::python::arg("data"), ""))
.def("load", &Loader::load);
- 在正确的 python 站点包中安装您的库。
- 在python中尽情享受:
from my_cool_package import MiddleClass, Loader
example_string = "whatever"
loader = Loader(data=example_string)
# Get the middle class
middle_class = loader.load()
# Print the data in the middle class
middle_class.print_data()
预期输出:
whatever
所以,我找到了解决办法。证明我错了,但我认为,我想要实现的目标是不可能的。
Python 具有不可变字符串,因此将 "reference" 字符串传递给函数并期望从函数内部更改它的能力根本无效。
以这段代码为例:
variable = "Hello"
def changer(var):
var = "Bye"
changer(variable)
print(variable)
打印 "Hello"。在 Python 中,您无法让它以不同的方式工作。 (虽然准确地说,它仍然作为引用传递,但是当你修改 Python 字符串时,你只是创建一个新的和一个新的引用)。
那么,如何解决这个问题?
简单!创建一个 C++ 包装器,它将处理对结果字符串的 std::string
和 return 副本传递引用。不是很有效,但你可能无法让它变得更好。
SaveWrapper
的示例代码class:
class SaveWrapper {
public:
// some constructor
std::string save(MiddleClass & value) {
std::string result;
Save saver(result);
saver.save(value);
return result;
}
};
可以轻松"ported"到Python!
我有一个 C++ 遗留代码(编辑起来会很痛苦),出于速度原因,我需要在 Python 2 中使用它。
我有两个类。一个负责从内存中加载大量数据,形式为std::string
,并将其转换为内部表示MiddleClass
。第二个是将其从内部表示 MiddleClass
转换回 std::string
.
class Load {
Load(const std::string & data) { ... };
MiddleClass load() { ... };
};
class Save {
Save(std::string & data) { .... };
void save(const MiddleClass & middleclass) { ... };
};
我的目标是,在 Python 2 中使用此设置,如下所示:
import datahandler # my lib
import requests
request = request.get("url-to-data")
loader = datahandler.Load(request.content) # my C++ class Load
internal_representation = loader.load()
.
.
.
result_variable = str() # or None or something not important
saver = datahandler.Save(result_variable) # my C++ class Save
saver.save(internal_representation)
我怎样才能做到这一点?
我 运行 从一开始就遇到了麻烦。
简单变体:
BOOST_PYTHON_MODULE(datahandler)
{
class_<MiddleClass>("MiddleClass");\
// some .defs - not important
class <Load>("Load", init<const std::string &>())
.def("load". &Load::load);
class <Save>("Save", init<std::string &>())
.def("save". &Save::save);
}
可以编译,不用担心,但是加载的数据不知何故被破坏了,这让我想到,我做的非常错误。
我还发现了 this 有点跑题的 SO 问题,它告诉我,我不能有 std::string &
,因为 Python 字符串是不可变的。
所以结论:我不知道现在该怎么办:(这里有人能帮我吗?谢谢。
参考这个工作示例。
- 定义你的 C++ 类。例如:
class MiddleClass {
public:
explicit MiddleClass(const std::string& data) : parent_data_(data) {}
void print() {
std::cout << parent_data_ << std::endl;
}
private:
std::string parent_data_;
};
class Loader {
public:
explicit Loader(const std::string& data) :
data_(data){
};
MiddleClass load() {
return MiddleClass(data_);
};
private:
std::string data_;
};
- 创建增强绑定
boost::python::class_<MiddleClass>("MiddleClass",
boost::python::init<const std::string&>(boost::python::arg("data"), ""))
.def("print_data", &MiddleClass::print);
boost::python::class_<Loader>("Loader",
boost::python::init<const std::string&>(boost::python::arg("data"), ""))
.def("load", &Loader::load);
- 在正确的 python 站点包中安装您的库。
- 在python中尽情享受:
from my_cool_package import MiddleClass, Loader
example_string = "whatever"
loader = Loader(data=example_string)
# Get the middle class
middle_class = loader.load()
# Print the data in the middle class
middle_class.print_data()
预期输出:
whatever
所以,我找到了解决办法。证明我错了,但我认为,我想要实现的目标是不可能的。
Python 具有不可变字符串,因此将 "reference" 字符串传递给函数并期望从函数内部更改它的能力根本无效。
以这段代码为例:
variable = "Hello"
def changer(var):
var = "Bye"
changer(variable)
print(variable)
打印 "Hello"。在 Python 中,您无法让它以不同的方式工作。 (虽然准确地说,它仍然作为引用传递,但是当你修改 Python 字符串时,你只是创建一个新的和一个新的引用)。
那么,如何解决这个问题?
简单!创建一个 C++ 包装器,它将处理对结果字符串的 std::string
和 return 副本传递引用。不是很有效,但你可能无法让它变得更好。
SaveWrapper
的示例代码class:
class SaveWrapper {
public:
// some constructor
std::string save(MiddleClass & value) {
std::string result;
Save saver(result);
saver.save(value);
return result;
}
};
可以轻松"ported"到Python!