Python C++ 右值的 SWIG 包装器 std::string &&
Python SWIG wrapper for C++ rvalue std::string &&
我正在尝试为 gnucash c++ 部分构建一个 python 包装器。在QofBackend中遇到了方法const std::string && get_message ()
。在 python 中,此消息 returns <Swig Object of type 'std::string *' at 0x7f4a20f5c9f0>
而不是我设置中的字符串,因为 std::string 右值引用没有 swig 类型映射。
我没有真正找到一个简单的解释,所以我重建了一个示例设置并深入研究了我几乎不了解的 c++。我设法将字符串放入 python 但我想知道
- 如果这种 typemap(out) 方法是正确的(也在内存和错误处理方面)。
set_s_workaround()
中的转换也只是一种解决方法。我认为对于 gnucash,python 代码不需要设置这个值,但为了完整起见,最好也有一个 typemap(in) std::string&&
和
- 去掉
get_s_workaround
- 开始 init_s_2 工作。
/* example.hpp */
#include <string>
using namespace std;
struct struct1{
string s;
const std::string&& get_s();
void set_s(string&&);
void set_s_workaround(string);
void init_s();
void init_s_2();
void print_s();
};
string conv_rvalue_string(string);
/* example.cpp */
#include<iostream>
#include"example.hpp"
using namespace std;
void
struct1::set_s (std::string&& msg)
{
s = msg;
}
std::string
conv_rvalue_string (std::string msg)
{
return msg;
}
void
struct1::set_s_workaround(std::string msg)
{
set_s ( conv_rvalue_string(msg) );
}
void
struct1::init_s ()
{
set_s("Some content");
}
void
struct1::init_s_2()
{
std::string msg {"Couldn't find "};
/* set_s( msg ); */
}
void
struct1::print_s ()
{
cout<<get_s()<<endl;
}
const std::string&&
struct1::get_s ()
{
return std::move(s);
}
/* example.i */
%module example
%include "std_string.i"
%typemap(out) std::string&& {
std::string s = *;
$result = SWIG_From_std_string(s);
}
%{
#include <string>
#include "example.hpp"
%}
%include "example.hpp"
#!/bin/bash
swig3.0 -c++ -shadow -python example.i
g++ -fpic -c example.hpp example.cpp example_wrap.cxx -I/usr/include/python3.7
g++ -shared example_wrap.o example.o -o _example.so
# pyexample.py
import example
s1 = example.struct1()
s1.set_s_workaround('TEST')
s1.print_s()
print(s1.get_s())
感谢您的帮助!
init_s2() 会像这样工作:
void
struct1::init_s_2()
{
std::string msg {"Couldn't find "};
set_s( msg + "");
}
感谢 S. Holtermann!
%typemap(out) std::string&& {
std::string s = *;
$result = SWIG_From_std_string(s);
}
可以缩短为
%typemap(out) std::string&& {
$result = SWIG_From_std_string(*);
}
无需创建本地变量(归功于 S. Holtermann!)
一个可能的 typemap(in) 可能是
%typemap(in) std::string && (std::string *temp){
int res = SWIG_AsPtr_std_string($input, &temp);
= temp;
}
- 有效
- 尚未经过广泛测试
- 会不会造成内存泄漏?
此 std::string &&
类型映射使用临时 std::string
传递给采用 std::string
右值引用的方法。
%typemap
中的片段依赖性确保使用的片段在包装文件中准备就绪。我们只是使用 "std_string.i"
.
已经提供的片段
/* example.i */
%module example
%include "std_string.i"
%typemap(out, fragment="SWIG_From_std_string") std::string&& {
$result = SWIG_From_std_string(*);
}
%typemap(in, fragment="SWIG_AsVal_std_string") std::string&& (std::string temp) {
int res = SWIG_AsVal_std_string($input, &temp);
= &temp;
}
%{
#include <string>
#include "example.hpp"
%}
%include "example.hpp"
我正在尝试为 gnucash c++ 部分构建一个 python 包装器。在QofBackend中遇到了方法const std::string && get_message ()
。在 python 中,此消息 returns <Swig Object of type 'std::string *' at 0x7f4a20f5c9f0>
而不是我设置中的字符串,因为 std::string 右值引用没有 swig 类型映射。
我没有真正找到一个简单的解释,所以我重建了一个示例设置并深入研究了我几乎不了解的 c++。我设法将字符串放入 python 但我想知道
- 如果这种 typemap(out) 方法是正确的(也在内存和错误处理方面)。
set_s_workaround()
中的转换也只是一种解决方法。我认为对于 gnucash,python 代码不需要设置这个值,但为了完整起见,最好也有一个typemap(in) std::string&&
和- 去掉
get_s_workaround
- 开始 init_s_2 工作。
/* example.hpp */
#include <string>
using namespace std;
struct struct1{
string s;
const std::string&& get_s();
void set_s(string&&);
void set_s_workaround(string);
void init_s();
void init_s_2();
void print_s();
};
string conv_rvalue_string(string);
/* example.cpp */
#include<iostream>
#include"example.hpp"
using namespace std;
void
struct1::set_s (std::string&& msg)
{
s = msg;
}
std::string
conv_rvalue_string (std::string msg)
{
return msg;
}
void
struct1::set_s_workaround(std::string msg)
{
set_s ( conv_rvalue_string(msg) );
}
void
struct1::init_s ()
{
set_s("Some content");
}
void
struct1::init_s_2()
{
std::string msg {"Couldn't find "};
/* set_s( msg ); */
}
void
struct1::print_s ()
{
cout<<get_s()<<endl;
}
const std::string&&
struct1::get_s ()
{
return std::move(s);
}
/* example.i */
%module example
%include "std_string.i"
%typemap(out) std::string&& {
std::string s = *;
$result = SWIG_From_std_string(s);
}
%{
#include <string>
#include "example.hpp"
%}
%include "example.hpp"
#!/bin/bash
swig3.0 -c++ -shadow -python example.i
g++ -fpic -c example.hpp example.cpp example_wrap.cxx -I/usr/include/python3.7
g++ -shared example_wrap.o example.o -o _example.so
# pyexample.py
import example
s1 = example.struct1()
s1.set_s_workaround('TEST')
s1.print_s()
print(s1.get_s())
感谢您的帮助!
init_s2() 会像这样工作:
void
struct1::init_s_2()
{
std::string msg {"Couldn't find "};
set_s( msg + "");
}
感谢 S. Holtermann!
%typemap(out) std::string&& {
std::string s = *;
$result = SWIG_From_std_string(s);
}
可以缩短为
%typemap(out) std::string&& {
$result = SWIG_From_std_string(*);
}
无需创建本地变量(归功于 S. Holtermann!)
一个可能的 typemap(in) 可能是
%typemap(in) std::string && (std::string *temp){
int res = SWIG_AsPtr_std_string($input, &temp);
= temp;
}
- 有效
- 尚未经过广泛测试
- 会不会造成内存泄漏?
此 std::string &&
类型映射使用临时 std::string
传递给采用 std::string
右值引用的方法。
%typemap
中的片段依赖性确保使用的片段在包装文件中准备就绪。我们只是使用 "std_string.i"
.
/* example.i */
%module example
%include "std_string.i"
%typemap(out, fragment="SWIG_From_std_string") std::string&& {
$result = SWIG_From_std_string(*);
}
%typemap(in, fragment="SWIG_AsVal_std_string") std::string&& (std::string temp) {
int res = SWIG_AsVal_std_string($input, &temp);
= &temp;
}
%{
#include <string>
#include "example.hpp"
%}
%include "example.hpp"