Menu

#1335 Bug with STL containers as attributes of C++ class and access from Python

None
open
nobody
None
5
2022-03-20
2013-09-22
Ian Bell
No

I have run into a problem with using STL containers (in this case std::vector<double> ) as member of a c++ class. If I provide (manually) a setter function, all is well, and in python I can pass a list (as I would like to do) as something like Comp.set_P([1,2,3]). But If I try to set the member using Comp.P = [1,2,3] (where Comp is an instance of CompressorClass in Python), no luck and I get an error it not being a std::vector<double> (but of course it isn't). Here's the error::</double></double>

File "setup.py", line 46, in <module>
Comp.P = [1.0,2.0,3.0]
File "src\Compressor.py", line 175, in <lambda>
setattr = lambda self, name, value: _swig_setattr(self, CompressorClass, name, value)
File "src\Compressor.py", line 49, in _swig_setattr
return _swig_setattr_nondynamic(self,class_type,name,value,0)
File "src\Compressor.py", line 42, in _swig_setattr_nondynamic
if method: return method(self,value)
TypeError: in method 'CompressorClass_P_set', argument 2 of type 'std::vector< double,std::allocator< double > > *'</lambda></module>

Shouldn't the setter function handle this properly? I think this is a bug.

Here is my header::

#ifndef COMPRESSOR_H
#define COMPRESSOR_H

#include "CPState.h"
#include "ACHPcore.h"

class CompressorClass// : public ACHPComponentClass
{
public:
    CompressorClass(){};
    ~CompressorClass(){};
    double Tsat_s_K, Tsat_d_K, DT_sh_K, Tsat_s, Tsat_d, power_map, Vdot_ratio, P1, P2, F, T1_actual, v_map, v_actual, mdot, fp, eta_oi, Wdot, CycleEnergyIn, Vdot_pumped;
    std::vector<double> P, M;

    CoolPropStateClass inlet_state, outlet_state;

    void set_P(std::vector<double> P){this->P = P;};
    void speed_test(unsigned long long N);
    void calculate();
    void test();
    std::vector<OutputEntryClass> OutputList();
};

#endif

and my interface file::

%module Compressor

// This stuff will get included verbatim in CoolProp_wrap.cpp
%{
#include "ACHPcore.h"
#include "Compressor.h"
%}

// This allows for the use of STL vectors
%include "std_vector.i"

namespace std {
   %template(vectord) vector<double>;
};

// This is where the parsing actually happens
%include "ACHPcore.h"
%include "Compressor.h"

Discussion

  • Olly Betts

    Olly Betts - 2022-03-20
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -14,7 +14,7 @@
    
     Here is my header::
    
    -
    +```
     #ifndef COMPRESSOR_H
     #define COMPRESSOR_H
    
    @@ -39,9 +39,10 @@
     };
    
     #endif
    -
    +```
     and my interface file::
    
    +```
     %module Compressor
    
     // This stuff will get included verbatim in CoolProp_wrap.cpp
    @@ -60,3 +61,4 @@
     // This is where the parsing actually happens
     %include &#34;ACHPcore.h&#34;
     %include &#34;Compressor.h&#34;
    +```
    
    • Group: -->
     
  • Olly Betts

    Olly Betts - 2022-03-20

    The example above is incomplete (missing headers and method definitions) but if I comment those out I can reproduce with SWIG git master.

    Compressor.h

    #ifndef COMPRESSOR_H
    #define COMPRESSOR_H
    
    //#include "CPState.h"
    //#include "ACHPcore.h"
    #include <vector>
    
    class CompressorClass// : public ACHPComponentClass
    {
    public:
        CompressorClass(){};
        ~CompressorClass(){};
        double Tsat_s_K, Tsat_d_K, DT_sh_K, Tsat_s, Tsat_d, power_map, Vdot_ratio, P1, P2, F, T1_actual, v_map, v_actual, mdot, fp, eta_oi, Wdot, CycleEnergyIn, Vdot_pumped;
        std::vector<double> P, M;
    
        //CoolPropStateClass inlet_state, outlet_state;
    
        void set_P(std::vector<double> P){this->P = P;};
        //void speed_test(unsigned long long N);
        //void calculate();
        //void test();
     //   std::vector<OutputEntryClass> OutputList();
    };
    
    #endif
    

    test.i

    %module Compressor
    
    // This stuff will get included verbatim in CoolProp_wrap.cpp
    %{
    //#include "ACHPcore.h"
    #include "Compressor.h"
    %}
    
    // This allows for the use of STL vectors
    %include "std_vector.i"
    
    namespace std {
       %template(vectord) vector<double>;
    };
    
    // This is where the parsing actually happens
    //%include "ACHPcore.h"
    %include "Compressor.h"
    

    Currently you need to convert to/from a vectord by hand, e.g.:

    >>> c.P = Compressor.vectord([1,2,3])
    >>> [x for x in c.P]
    [1.0, 2.0, 3.0]
    
     

    Last edit: Olly Betts 2022-03-20

Log in to post a comment.