1

MSVC2010 を搭載した Windows で Boost.Python 1.54 を使用していますが、1 つのクラスへのポインターを Python の 2 番目のクラスに格納して取得する際に問題があります。どういうわけかデータ型を変更するようです。

これが私のクラスです:

typedef unsigned int uint_t;

struct classA {
  int intval;
  unsigned int bitfield_member:1;
};

struct Collection {
  classA * class_a_ptr;
};

そして、これが私がそれらをPythonに公開する方法です(このコードの一部はもともとPy ++によって自動生成されましたが、それ以来手作業で編集しました):

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/manage_new_object.hpp>

namespace bp = boost::python;

struct Collection_wrapper : Collection, bp::wrapper< Collection > {

    Collection_wrapper(Collection const & arg )
    : Collection( arg )
      , bp::wrapper< Collection >(){
        // copy constructor

    }

    Collection_wrapper()
    : Collection()
      , bp::wrapper< Collection >(){
        // null constructor

    }

    static ::classA * get_class_a_ptr(Collection const & inst ){
        return inst.class_a_ptr;
    }

    static void set_class_a_ptr( Collection & inst, ::classA * new_value ){
        inst.class_a_ptr = new_value;
    }
};

struct classA_wrapper : classA, bp::wrapper< classA > {

    classA_wrapper(classA const & arg )
    : classA( arg )
      , bp::wrapper< classA >(){
        // copy constructor

    }

    classA_wrapper()
    : classA()
      , bp::wrapper< classA >(){
        // null constructor

    }

    ::uint_t get_bitfield_member() const {
        return bitfield_member;
    }

    void set_bitfield_member( ::uint_t new_value ){
        bitfield_member = new_value;
    }
};

BOOST_PYTHON_MODULE(render_lib_ext)

{
  using namespace bp;

    { //::Collection
        typedef bp::class_< Collection_wrapper > Collection_exposer_t;
        Collection_exposer_t Collection_exposer = Collection_exposer_t( "Collection" );
        bp::scope Collection_scope( Collection_exposer );
    // original version, fails
    Collection_exposer.add_property( "class_a_ptr"
                    , bp::make_function( (::classA * (*)( ::Collection const & ))(&Collection_wrapper::get_class_a_ptr), bp::return_internal_reference< >() )
                    , bp::make_function( (void (*)( ::Collection &,::classA * ))(&Collection_wrapper::set_class_a_ptr), bp::with_custodian_and_ward_postcall< 1, 2 >() ) );
    }

  { //::classA
    typedef bp::class_< classA_wrapper > classA_exposer_t;
    classA_exposer_t classA_exposer = classA_exposer_t( "classA" );
    bp::scope classA_scope( classA_exposer );
    classA_exposer.def_readwrite( "intval", &classA::intval );
    classA_exposer.add_property( "bitfield_member"
                   , (::uint_t ( classA_wrapper::* )(  ) const)(&classA_wrapper::get_bitfield_member)
                   , (void ( classA_wrapper::* )( ::uint_t ) )(&classA_wrapper::set_bitfield_member) );
  }
}

そして、これを実行するためのpythonテストは次のとおりです。

import unittest
import render_lib_ext as RL

class TestRenderLib(unittest.TestCase):

    def test_globals(self):
        coll=RL.Collection()
        g = RL.classA()
        g.intval=9801;
        self.assertEqual(9801, g.intval)
        coll.class_a_ptr = g # store pointer in collection
        geg = coll.class_a_ptr # retrieve it
        self.assertEqual(0, g.bitfield_member) # works
        self.assertEqual(0, geg.bitfield_member) # fails with ArgumentError (type error)
        self.assertEqual(9801, geg.intval)    # fails!  Is it not the same object?

最初の「fails」行で次のエラーで失敗します。

Traceback (most recent call last):
  File "test2.py", line 18, in test_globals
    self.assertEqual(0, geg.bitfield_member) # fails with ArgumentError (type error)
ArgumentError: Python argument types in
    None.None(classA)
did not match C++ signature:
    None(struct classA_wrapper {lvalue})

classA_wrapper は classA を拡張するので、これは奇妙に思えます。私は何を間違っていますか?これを行う別の方法はありますか?私は Python と C++ の経験が豊富ですが、Boost.Python への挑戦はこれが初めてです。

4

1 に答える 1