Discussion:
[C++-sig] register c++ std::pair<string, string> and std::pair<string*, string*>
MM
2015-08-28 11:49:53 UTC
Permalink
I expose the return type of a C++ function that is a pair of strings with
the following snippet:

to_python_converter<
std::pair<std::string, std::string>,
Converter>();

Later, I have a unrelated C++ range type:

typedef std::pair<const std::string*,const std::string*> range_t;

which I export as:

class_<range_t>("range")
.def("__iter__" , range(..., ...));
scope().attr("allitems") = object(ptr(&R));

where R is of type range_t

in python, allitems can be iterated over.

The only issue is I get the following warning:

/usr/lib64/python3.4/importlib/_bootstrap.py:321: RuntimeWarning:
to-Python converter for std::pair<std::string const*, std::string
const*> already registered; second conversion method ignored.

Is there a way to avoid this warning?

MM
Stefan Seefeld
2015-08-28 12:41:31 UTC
Permalink
Post by MM
I expose the return type of a C++ function that is a pair of strings
|to_python_converter<std::pair<std::string,std::string>,Converter>();|
|typedef std::pair<const std::string*,const std::string*>range_t;|
|class_<range_t>("range").def("__iter__",range(...,...));scope().attr("allitems")=object(ptr(&R));|
where R is of type range_t
in python, allitems can be iterated over.
|/usr/lib64/python3.4/importlib/_bootstrap.py:321:RuntimeWarning:to-Pythonconverter
forstd::pair<std::string const*,std::string const*>already
registered;second conversion method ignored.|
Is there a way to avoid this warning?
Why do you need the explicit converter if you also define a
class_<range_t> ? Wouldn't everything work just fine without it ?

Stefan
--
...ich hab' noch einen Koffer in Berlin...
MM
2015-08-28 13:26:53 UTC
Permalink
Post by MM
Post by MM
I expose the return type of a C++ function that is a pair of strings
|to_python_converter<std::pair<std::string,std::string>,Converter>();|
|typedef std::pair<const std::string*,const std::string*>range_t;|
|class_<range_t>("range").def("__iter__",range(...,...));scope().attr("allitems")=object(ptr(&R));|
Post by MM
where R is of type range_t
in python, allitems can be iterated over.
|/usr/lib64/python3.4/importlib/_bootstrap.py:321:RuntimeWarning:to-Pythonconverter
Post by MM
forstd::pair<std::string const*,std::string const*>already
registered;second conversion method ignored.|
Is there a way to avoid this warning?
Why do you need the explicit converter if you also define a
class_<range_t> ? Wouldn't everything work just fine without it ?
Stefan
This is in too separate modules.
The converter is registered in module1, and the class_<range_t> in module 2.
I import 1 then 2, then it happens

Also the intents are different. THe pair<string,string> is to be considered
as a (str1,str2) tuple of 2 values.
The pair<string*, string*> is the [begin, end[ iterators into an array with
value_type string
Stefan Seefeld
2015-08-28 14:01:18 UTC
Permalink
Post by MM
This is in too separate modules.
The converter is registered in module1, and the class_<range_t> in module 2.
I import 1 then 2, then it happens
Also the intents are different. THe pair<string,string> is to be
considered as a (str1,str2) tuple of 2 values.
The pair<string*, string*> is the [begin, end[ iterators into an array
with value_type string
Oups, sorry, I hadn't noticed that they had different types. Can you
please post a minimal bug self-contained test case ? I'd like to debug
this a bit to better understand what is going on. I believe this should
work as there is no reason the two types should be confused. (It
obviously depends on your "Converter" type, which you haven't shown.)

Thanks,
Stefan
--
...ich hab' noch einen Koffer in Berlin...
MM
2015-08-28 14:15:50 UTC
Permalink
Post by Stefan Seefeld
Post by MM
This is in too separate modules.
The converter is registered in module1, and the class_<range_t> in module 2.
I import 1 then 2, then it happens
Also the intents are different. THe pair<string,string> is to be
considered as a (str1,str2) tuple of 2 values.
The pair<string*, string*> is the [begin, end[ iterators into an array
with value_type string
Oups, sorry, I hadn't noticed that they had different types. Can you
please post a minimal bug self-contained test case ? I'd like to debug
this a bit to better understand what is going on. I believe this should
work as there is no reason the two types should be confused. (It
obviously depends on your "Converter" type, which you haven't shown.)
Thanks,
Stefan
Well, there's something about the fact that pointer types somehow change to
the types pointed to.... I don't understand it well

I tried to strip it down here:

/// header file
template <typename T1, typename T2>
struct stdpair_to_python_tuple
{
static PyObject* convert(const std::pair<T1,T2>&pr)
{
return incref( make_tuple(pr.first, pr.second).ptr() );
}
};

/// module1.cpp
BOOST_PYTHON_MODULE(libmodule1)
{
to_python_converter<
std::pair<std::string, std::string>,
stdpair_to_python_tuple<std::string,std::string>>();
}

/// module2.cpp
typedef std::pair<const std::string*,const std::string*> range_t;
range_t range;

BOOST_PYTHON_MODULE(libmodule2)
{
using namespace boost::python;

class_<range_t>("range")
.def("__iter__",
range(&range_t::first, &range_t::second))
;

scope().attr("allitems") = object(ptr(&range));
}


Load 1 then 2 it should trigger the warning.
Apologies for missing the includes.

Thanks
Stefan Seefeld
2015-08-28 14:20:22 UTC
Permalink
Post by Stefan Seefeld
Post by MM
This is in too separate modules.
The converter is registered in module1, and the class_<range_t> in module 2.
I import 1 then 2, then it happens
Also the intents are different. THe pair<string,string> is to be
considered as a (str1,str2) tuple of 2 values.
The pair<string*, string*> is the [begin, end[ iterators into an
array
Post by MM
with value_type string
Oups, sorry, I hadn't noticed that they had different types. Can you
please post a minimal bug self-contained test case ? I'd like to debug
this a bit to better understand what is going on. I believe this should
work as there is no reason the two types should be confused. (It
obviously depends on your "Converter" type, which you haven't shown.)
Thanks,
Stefan
Well, there's something about the fact that pointer types somehow
change to the types pointed to.... I don't understand it well
Yes, sure: by default, if you pass a pointer-to-A to Python, it will
actually pass the A, unless you use the 'ptr()' wrapper. But that
doesn't mean a container-to-A and container-to-pointer-to-A should be
confused...

I'll look at your sample code, thank.
Stefan
--
...ich hab' noch einen Koffer in Berlin...
Stefan Seefeld
2015-08-28 15:05:34 UTC
Permalink
Post by MM
Load 1 then 2 it should trigger the warning.
Apologies for missing the includes.
I had to modify your code a bit as it triggers errors when compiled
as-is. And with those modifications it didn't see any warning.
Could you please post code that I can compile without any modifications ?

Thanks,
Stefan
--
...ich hab' noch einen Koffer in Berlin...
MM
2015-08-28 15:41:03 UTC
Permalink
Post by Stefan Seefeld
Post by MM
Load 1 then 2 it should trigger the warning.
Apologies for missing the includes.
I had to modify your code a bit as it triggers errors when compiled
as-is. And with those modifications it didn't see any warning.
Could you please post code that I can compile without any modifications ?
Thanks,
Stefan
Apologies, I also didn't get any warnings.

I was actually registering an identical std::pair<const string*, const
string*> as an iterator with a different name in a prior module, ie I had
another class_<range2_t>("range2")

and range2_t is identical to ranget_t :-)

Thanks for helping to spot this:-)
Stefan Seefeld
2015-08-28 15:42:55 UTC
Permalink
Post by Stefan Seefeld
Post by MM
Load 1 then 2 it should trigger the warning.
Apologies for missing the includes.
I had to modify your code a bit as it triggers errors when compiled
as-is. And with those modifications it didn't see any warning.
Could you please post code that I can compile without any
modifications ?
Thanks,
Stefan
Apologies, I also didn't get any warnings.
I was actually registering an identical std::pair<const string*,
const string*> as an iterator with a different name in a prior module,
ie I had another class_<range2_t>("range2")
and range2_t is identical to ranget_t :-)
Aha ! Yeah, that's clearly not going to work due to the ambiguity.
Post by Stefan Seefeld
Thanks for helping to spot this:-)
Welcome !:-)

Stefan
--
...ich hab' noch einen Koffer in Berlin...
Loading...