如何使“自己”C++字符串类自动转换为绑定中的Python字符串

2024-04-27 05:22:38 发布

您现在位置:Python中文网/ 问答频道 /正文

C++代码

class MyOwnString; // assume this implements a string class.

class HasMyOwnString // simple example that uses it
{
 private:
MyOwnString m_name;
int m_age;

  public:
HasMyOwnString( MyOwnString const& name, int age ) :
  m_name( name ), m_age( age )
{
}

MyOwnString name() const
{
    return m_name;
}

int age() const
{
    return m_age;
}
};

class HasStdString
{
   private:
std::string m_name;
int m_age;

   public:
HasStdString( std::string const& name, int age ) :
  m_name( name ), m_age( age )
{
}

std::string name() const
{
    return m_name;
}

int age() const
{
    return m_age;
}
};

BOOST_PYTHON_MODULE(test_cpp)
{
using namespace boost::python;
using boost::noncopyable;

class_<HasMyOwnString>( "HasMyOwnString", init<MyOwnString, int>() )
    .def( "name", &HasMyOwnString::name )
    .def( "age", &HasMyOwnString::age );

class_<HasStdString>( "HasStdString", init<std::string, int>() )
    .def( "name", &HasStdString::name )
    .def( "age", &HasStdString::age );
}

假设所有相关标题都已包含。上面的代码确实构建在python.pyd中。在

下面是我想使用的Python:

^{pr2}$

Python的第一部分工作,即HasStdString。它知道如何自动将Python str输入转换为std::string,以便绑定工作。在

第二部分无法预期MyOwnString。在

  1. MyOwnString有一个const char*的隐式构造函数
  2. 我尝试过各种方法,加入了boost的一些重载,但是没有找到任何有效的方法。在

我搜索了boost的代码,看看它们是如何让str自动转换为std::string的。中的宏操作员.hpp一点意义都没有。内置宏_转换器.hpp确实有道理,但它们似乎以另一种方式进行所有转换(除了在我的1.50.0版本中存在编译器错误之外),并没有解决问题。在

实际上,我尝试向Python公开的API有它自己的string类。好吧,已经够糟糕的了,我无法改变。但我希望这不会对Python用户产生影响,我希望等效Python API在C++代码中使用“自定义”字符串时使用Python字符串。我想在一个地方定义转换,然后为了它能在任何地方工作,我绑定了一个函数。在

(为了那些希望使用MyOwnString实现的用户,我在这里创建了自己的MyOwnString实现)

class MyOwnString
{
public:
    MyOwnString() 
      : m_internal()
    {
        init();
    }

    MyOwnString( const char * val ) 
        : m_internal()
    {
        init();
        assign( val, strlen( val ) );
    }

    MyOwnString( MyOwnString const& other )
        : m_internal()
    {
        init();
        assign( other.c_str(), other.m_len );
    }

    MyOwnString( const char * val, size_t len )
        : m_internal()
    {
        init();
        assign( val, len );
    }

    ~MyOwnString()
    {
        cleanup();
    }

    const char * c_str() const
    {
        return m_data;
    }

    size_t size() const
    {
        return m_len;
    }

    bool empty() const
    {
        return m_len == 0;
    }

    void clear()
    {
        cleanup();
        m_internal[0] = '\0';
    }

    MyOwnString & operator=( MyOwnString const& other )
    {
        assign( other.c_str(), other.m_len );
        return *this;
    }

    MyOwnString & operator=( const char * val )
    {
        assign( val, strlen(val) );
        return *this;
    }

private:

    void init()
    {
        m_data = m_internal;
        m_capacity = 0;
        m_len = 0;
    }

    void cleanup()
    {
        if( m_data != m_internal )
        {
            delete [] m_data;
            m_capacity = 0;
            m_data = m_internal;
        }
    }

    void assign( const char * text, size_t len ) // length not including null
    {
        if( len < EInternalSize ) // it fits into internal buffer
        {
            memcpy( m_internal, text, len );
            m_internal[len]='\0';
            cleanup(); // if we have dynamically allocated data remove it
            m_len = len;
        }
        else if( m_capacity > len ) // fits into already assigned buffer
        {
            memcpy( m_data, text, len );
            m_internal[len]='\0';
            m_len = len;
        }
        else
        {
            // We need to allocate. Do that before we delete any existing buffer

            char * buf = new char[ len + 1 ];
            memcpy( buf, text, len );
            buf[len] = '\0';

            cleanup(); // if there was a buffer there remove it
            m_data = buf;
            m_capacity = len + 1;
            m_len = len;
        }
    }


    enum { EInternalSize = 16 };
    size_t m_len;
    size_t m_capacity;
    char m_internal[EInternalSize];
    char * m_data;
};

总结一下问题是:

我需要在绑定中添加什么来允许hasmoywnstring的绑定像提供的Python一样工作。。。在

(我不介意更改hasmoywnstring中的init部分,我希望其他不需要我提供参数类型的函数都能正常工作)。在


Tags: nameagedatastringlenreturninitval