[C++-sig] [boost.python] Can't import a wrapped template class
Hi all,
right now I'm doing my first stepps in wrapping C++ code by ude of Boost.
So, there's a
template class _Variable
with ctor, dtor, an inspector
TYPE value() const
and a mutator
void value( const TYPE& value).
The boost wrapper looks like this:
#include
#include
using namespace boost::python;
#include "./src/varbls.h"
#include
using namespace std;
typedef _Variable VariableDouble;
BOOST_PYTHON_MODULE(_varbls)
{
class_("VariableDouble")
.def( init<>())
.def( init())
;
}
Nothing special so far. However, what I get upon import is this:
ImportError:
/usr/lib/python2.7/site-packages/tau4.DDG/tau4/tau4misc/varbls/cpp/boost/_varbls.so:
undefined symbol: _ZN9_VariableIdEC1Ev
The ctor is decl'ed as
_Variable();
and ist's def'ed like so:
template
_Variable::_Variable()
: _value( 0)
{
//ctor
}
To me, everything looks good, but obiously there's something wrong. What
do I miss?
Paul
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 07:42 AM, Paul O. Seidon wrote: > Hi all, > > right now I'm doing my first stepps in wrapping C++ code by ude of Boost. [...] Where is the definition of your _Variable template instances ? Your newly compiled Python module can't find them. The likely cause is that you forgot to link the module to the library containing the definition(s). Stefan -- ...ich hab' noch einen Koffer in Berlin... ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
Stefan Seefeld wrote:
> On 10/26/2012 07:42 AM, Paul O. Seidon wrote:
>> Hi all,
>>
>> right now I'm doing my first stepps in wrapping C++ code by ude of Boost.
>
> [...]
>
> Where is the definition of your _Variable template instances ? Your
> newly compiled Python module can't find them. The likely cause is that
> you forgot to link the module to the library containing the definition(s).
>
> Stefan
>
>
Not sure what you mean:
The ctor is decl'ed in varbls.h as
_Variable();
and it's def'ed in varbls.cpp like so:
template
_Variable::_Variable()
: _value( 0)
{
//ctor
}
I did a typedef in the wrapper and wrote
BOOST_PYTHON_MODULE(_varbls)
{
class_("VariableDouble")
.def( init<>())
.def( init())
;
}
in the wrapper.
Any instance of VariableDouble should then be def'ed in the importing Python
module.
Everything works fine if I do not use templates but plain C++ classes
instead.
Paul
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 01:50 PM, Paul O. Seidon wrote:
> The ctor is decl'ed in varbls.h as
>
> _Variable();
>
> and it's def'ed in varbls.cpp like so:
>
> template
> _Variable::_Variable()
> : _value( 0)
> {
> //ctor
> }
That doesn't work. When the compiler compiles varbls.cpp, it doesn't
know what types to instantiate the _Variable template for, so you need
to either explicitly instantiate it for all the types you use in your
module, or keep the definitions in the varbls.h header so the compiler
can implicitly instantiate them when compiling the Python module.
Stefan
--
...ich hab' noch einen Koffer in Berlin...
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
Stefan Seefeld wrote:
> On 10/26/2012 01:50 PM, Paul O. Seidon wrote:
>> The ctor is decl'ed in varbls.h as
>>
>> _Variable();
>>
>> and it's def'ed in varbls.cpp like so:
>>
>> template
>> _Variable::_Variable()
>> : _value( 0)
>> {
>> //ctor
>> }
>
> That doesn't work. When the compiler compiles varbls.cpp, it doesn't
> know what types to instantiate the _Variable template for, so you need
> to either explicitly instantiate it for all the types you use in your
> module, or keep the definitions in the varbls.h header so the compiler
> can implicitly instantiate them when compiling the Python module.
>
> Stefan
>
That didn't make any difference. And it would have surprised me, if it did:
varbls.h contains the declaration, varbls.cpp contains the definition, the
wrapper is in main.cpp. So if the compiler sees any need to include
sometihng, it will and the linker will link the definition.
But you certainly are right, the symbol is in the .so-file but the symbol
isn't resolved by the linker. Hm, but where should I instantiate the class?
I thought
BOOST_PYTHON_MODULE(_varbls)
{
class_("VariableDouble")
.def( init<>())
.def( init())
;
}
would do that. Should I try
dont_care = _Variable();
in main.cpp? Looks a bit strange, but would force the compiler to generate
code for sure.
Paul
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
Paul O. Seidon wrote:
> Stefan Seefeld wrote:
>
>> On 10/26/2012 01:50 PM, Paul O. Seidon wrote:
>>> The ctor is decl'ed in varbls.h as
>>>
>>> _Variable();
>>>
>>> and it's def'ed in varbls.cpp like so:
>>>
>>> template
>>> _Variable::_Variable()
>>> : _value( 0)
>>> {
>>> //ctor
>>> }
>>
>> That doesn't work. When the compiler compiles varbls.cpp, it doesn't
>> know what types to instantiate the _Variable template for, so you need
>> to either explicitly instantiate it for all the types you use in your
>> module, or keep the definitions in the varbls.h header so the compiler
>> can implicitly instantiate them when compiling the Python module.
>>
>> Stefan
>>
>
> That didn't make any difference. And it would have surprised me, if it
> did: varbls.h contains the declaration, varbls.cpp contains the
> definition, the wrapper is in main.cpp. So if the compiler sees any need
> to include sometihng, it will and the linker will link the definition.
>
> But you certainly are right, the symbol is in the .so-file but the symbol
> isn't resolved by the linker. Hm, but where should I instantiate the
> class? I thought
>
> BOOST_PYTHON_MODULE(_varbls)
> {
>
> class_("VariableDouble")
> .def( init<>())
> .def( init())
> ;
> }
>
> would do that. Should I try
>
> dont_care = _Variable();
>
> in main.cpp? Looks a bit strange, but would force the compiler to generate
> code for sure.
>
> Paul
That doesn't do it either. I can't help but post the compete code here to be
sure I'm not misunderstood. The lib consists of varbls.cpp and varbls.h and
the wrapper main.cpp.
varbls.h
#ifndef VARBLS_H
#define VARBLS_H
template
class _Variable
{
public:
_Variable();
_Variable( const TYPE& v);
virtual ~_Variable();
TYPEvalue() const;
voidvalue( const double& v);
protected:
private:
TYPE_value;
};
/*
class VariableFloat : public _Variable
{
public:
VariableFloat( const double& v)
: _Variable( v)
{};
virtual ~VariableFloat()
{};
};
*/
class VariableFloat
{
public:
VariableFloat( const double& v=0)
: _value( v)
{};
virtual ~VariableFloat()
{};
double value() const
{ return _value;
};
voidvalue( const double& v)
{ _value = v;
};
private:
double _value;
};
#endif // VARBLS_H
varbls.cpp
==
#include "varbls.h"
template
_Variable::_Variable()
: _value( 0)
{
//ctor
}
template
_Variable::_Variable( const TYPE& v)
: _value( v)
{
//ctor
}
template
_Variable::~_Variable()
{
//dtor
}
template TYPE _Variable::value() const
{
return _value;
}
template void _Variable::value( const double& v)
{
_value = v;
}
main.cpp
#include
#include
using namespace boost::python;
#include "./src/varbls.h"
#include
using namespace std;
typedef _Variable VariableDouble;
/*
void(VariableFloat::*value_1)( const double& ) = &VariableFloat::value;
double (VariableFloat::*value_2)() const = &VariableFloat::value;
*/
BOOST_PYTHON_MODULE(_varbls)
{
class_("VariableDouble")
.def( init<>())
.def( init())
;
/*
class_("VariableFloat")
.def( init<>())
.def( init())
.def( "value", value_1)
.def( "value", value_2)
;
*/
}
VariableDouble _DONT_CARE = VariableDouble();
Paul
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 02:16 PM, Paul O. Seidon wrote:
> Stefan Seefeld wrote:
>
>> On 10/26/2012 01:50 PM, Paul O. Seidon wrote:
>>> The ctor is decl'ed in varbls.h as
>>>
>>> _Variable();
>>>
>>> and it's def'ed in varbls.cpp like so:
>>>
>>> template
>>> _Variable::_Variable()
>>> : _value( 0)
>>> {
>>> //ctor
>>> }
>> That doesn't work. When the compiler compiles varbls.cpp, it doesn't
>> know what types to instantiate the _Variable template for, so you need
>> to either explicitly instantiate it for all the types you use in your
>> module, or keep the definitions in the varbls.h header so the compiler
>> can implicitly instantiate them when compiling the Python module.
>>
>> Stefan
>>
> That didn't make any difference. And it would have surprised me, if it did:
> varbls.h contains the declaration, varbls.cpp contains the definition, the
> wrapper is in main.cpp. So if the compiler sees any need to include
> sometihng, it will and the linker will link the definition.
Sorry, let's back up a little. What are you referring to as "the
definition" in the above ?
Where is the "_Variable::_Variable()" constructor defined ? You
didn't show me where it was. You only showed me the (still parametrized)
definition in varbls.cpp. If the compiler sees the parametrized
constructor definition, it doesn't know what types to instantiate it
for, so it does nothing (other than validate the code to some degree).
It's only when it instantiates the template for a particular type that
it generates the missing symbol.
But - according to the small chunks of code you have shown me - it only
attempts that instantiation implicitly in your module's code. But at
that point it doesn't see the constructor definition, so it can't
instantiate that.
Perhaps showing a little more of your code / setup would help.
Stefan
--
...ich hab' noch einen Koffer in Berlin...
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 11:16 AM, Paul O. Seidon wrote: would do that. Should I try dont_care = _Variable(); in main.cpp? Looks a bit strange, but would force the compiler to generate code for sure. You either need to inline the ctor in the header or do an explicit instantiation of _Variable somewhere. I suggest you read up on "explicit instantiation" and c++ templates in general. This problem isn't related to boost.python. Alex ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 02:24 PM, Paul O. Seidon wrote:
> Paul O. Seidon wrote:
>
> That doesn't do it either. I can't help but post the compete code here to be
> sure I'm not misunderstood. The lib consists of varbls.cpp and varbls.h and
> the wrapper main.cpp.
> varbls.cpp
> ==
>
> #include "varbls.h"
>
>
> template
> _Variable::_Variable()
> : _value( 0)
> {
> //ctor
> }
[...]
What symbols does your compiled varbls.o file export ? I bet none. And
it can't. That's the problem I'm trying to explain.
Stefan
--
...ich hab' noch einen Koffer in Berlin...
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
Stefan Seefeld wrote:
> On 10/26/2012 02:24 PM, Paul O. Seidon wrote:
>> Paul O. Seidon wrote:
>>
>> That doesn't do it either. I can't help but post the compete code here to
>> be sure I'm not misunderstood. The lib consists of varbls.cpp and
>> varbls.h and the wrapper main.cpp.
>
>> varbls.cpp
>> ==
>>
>> #include "varbls.h"
>>
>>
>> template
>> _Variable::_Variable()
>> : _value( 0)
>> {
>> //ctor
>> }
>
> [...]
>
> What symbols does your compiled varbls.o file export ? I bet none. And
> it can't. That's the problem I'm trying to explain.
>
> Stefan
>
As Alex said, this seems to be a C++ issue. Hope you'll help me
nevertheless. There can't be that much that's missing.
How do I do that export?
This whole mess is caused by the use of a template class. You see, there's a
class VariableFloat. It is not a template class and is not derived from a
template class. And it works, I can use it from w/i my Python modules. Well,
it's deactivated for now to prevent "side effects".
Yes, I have to provide a TYPE to the tempate to enable the compiler to
generate code. Isn't
typedef _Variable VariableDouble;
BOOST_PYTHON_MODULE(_varbls)
{
class_("VariableDouble")
.def( init<>())
.def( init())
;
}
doing that?
Paul
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 04:15 PM, Paul O. Seidon wrote:
> Yes, I have to provide a TYPE to the tempate to enable the compiler to
> generate code. Isn't
>
> typedef _Variable VariableDouble;
>
> BOOST_PYTHON_MODULE(_varbls)
> {
>
> class_("VariableDouble")
> .def( init<>())
> .def( init())
> ;
> }
>
> doing that?
The compiler can only generate code from templates it can see at the
point where the instantiation happens. Since in the snippet above it
doesn't see the _Variable constructor definition, it can't instantiate
it. And at the point where it can see the constructor, it doesn't know
that it needs to instantiate it for type 'double'.
The entire issue disappears if you move your member function definitions
(including the constructor) from varbls.cpp to varbls.h.
Stefan
--
...ich hab' noch einen Koffer in Berlin...
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] [boost.python] Can't import a wrapped template class
On 10/26/2012 1:27 PM, Stefan Seefeld wrote: The entire issue disappears if you move your member function definitions (including the constructor) from varbls.cpp to varbls.h. Alternatively, explicitly instantiate in varbls.cpp. template class _Variable; Again, you might want to google "explicit template instantiation" or similar. Alex ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
