C++ 使boost::python尊重数据对齐

C++ 使boost::python尊重数据对齐,c++,python,boost,boost-python,C++,Python,Boost,Boost Python,我正在为我的项目编写python包装器,该项目使用Eigen进行数学计算。在测试基本操作之后,python内部创建的特征对象总是返回错误的结果。这通常发生在我不尊重使用Eigen进行数据对齐时。这可以通过使用eigen::aligned_分配器分配eigen对象来解决。我如何告诉boost使用eigen::aligned_分配器分配eigen对象 下面是一个简单的测试: C++ 我们希望它打印身份矩阵,但结果总是不同的。< P>控制C++类型的分配,将工厂函数登记为Python对象的构造函数。通

我正在为我的项目编写python包装器,该项目使用Eigen进行数学计算。在测试基本操作之后,python内部创建的特征对象总是返回错误的结果。这通常发生在我不尊重使用Eigen进行数据对齐时。这可以通过使用eigen::aligned_分配器分配eigen对象来解决。我如何告诉boost使用eigen::aligned_分配器分配eigen对象

下面是一个简单的测试:

C++


我们希望它打印身份矩阵,但结果总是不同的。

< P>控制C++类型的分配,将工厂函数登记为Python对象的构造函数。通常情况下,自定义分配也意味着自定义解除分配,在这种情况下,
boost::shared_ptr
可用于管理对象的生存期并调用自定义解除分配策略。这将涉及更多细节,但这里是一个带有基本自定义分配器的完整示例

#include <cstdlib>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>

///  @brief Basic custom allocator.
template <typename T>
class custom_allocator
{
public:
  typedef size_t size_type;
  typedef T*     pointer;
  typedef T      value_type;
public:
  pointer allocate(size_type num, const void* hint = 0)
  {
    std::cout << "custom_allocator::allocate()" << std::endl;
    return reinterpret_cast<pointer>(
      std::malloc(num * sizeof(value_type)));
  }

  void deallocate(pointer p, size_type num)
  {
    std::cout << "custom_allocator::deallocate()" << std::endl;
    std::free(p);
  }
};

/// @brief Example class.
class foo
{
public:
  foo()         { std::cout << "foo()" << std::endl; }
  ~foo()        { std::cout << "~foo()" << std::endl; } 
  void action() { std::cout << "foo::action()" << std::endl; }
};

/// @brief Allocator for foo.
custom_allocator<foo> foo_allocator;

/// @brief Destroy a foo object.
void destroy_foo(foo* p)
{
  p->~foo();                      // Destruct.
  foo_allocator.deallocate(p, 1); // Deallocate.
}

/// @brief Factory function to create a foo object.
boost::shared_ptr<foo> create_foo()
{
  void* memory = foo_allocator.allocate(1); // Allocate.
  return boost::shared_ptr<foo>(
    new (memory) foo(), // Construct in allocated memory.
    &destroy_foo);      // Use custom deleter.
}

BOOST_PYTHON_MODULE(example) {
  namespace python = boost::python;
  // Expose foo, that will be managed by shared_ptr, and transparently
  // constructs the foo via a factory function to allow for a custom
  // deleter to use the custom allocator.
  python::class_<foo, boost::shared_ptr<foo>, 
                 boost::noncopyable>("Foo", python::no_init)
    .def("__init__", python::make_constructor(&create_foo))
    .def("action", &foo::action)
    ;
}

为控制C++类型的分配,将工厂函数登记为Python对象的构造函数。通常情况下,自定义分配也意味着自定义解除分配,在这种情况下,

boost::shared_ptr
可用于管理对象的生存期并调用自定义解除分配策略。这将涉及更多细节,但这里是一个带有基本自定义分配器的完整示例

#include <cstdlib>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>

///  @brief Basic custom allocator.
template <typename T>
class custom_allocator
{
public:
  typedef size_t size_type;
  typedef T*     pointer;
  typedef T      value_type;
public:
  pointer allocate(size_type num, const void* hint = 0)
  {
    std::cout << "custom_allocator::allocate()" << std::endl;
    return reinterpret_cast<pointer>(
      std::malloc(num * sizeof(value_type)));
  }

  void deallocate(pointer p, size_type num)
  {
    std::cout << "custom_allocator::deallocate()" << std::endl;
    std::free(p);
  }
};

/// @brief Example class.
class foo
{
public:
  foo()         { std::cout << "foo()" << std::endl; }
  ~foo()        { std::cout << "~foo()" << std::endl; } 
  void action() { std::cout << "foo::action()" << std::endl; }
};

/// @brief Allocator for foo.
custom_allocator<foo> foo_allocator;

/// @brief Destroy a foo object.
void destroy_foo(foo* p)
{
  p->~foo();                      // Destruct.
  foo_allocator.deallocate(p, 1); // Deallocate.
}

/// @brief Factory function to create a foo object.
boost::shared_ptr<foo> create_foo()
{
  void* memory = foo_allocator.allocate(1); // Allocate.
  return boost::shared_ptr<foo>(
    new (memory) foo(), // Construct in allocated memory.
    &destroy_foo);      // Use custom deleter.
}

BOOST_PYTHON_MODULE(example) {
  namespace python = boost::python;
  // Expose foo, that will be managed by shared_ptr, and transparently
  // constructs the foo via a factory function to allow for a custom
  // deleter to use the custom allocator.
  python::class_<foo, boost::shared_ptr<foo>, 
                 boost::noncopyable>("Foo", python::no_init)
    .def("__init__", python::make_constructor(&create_foo))
    .def("action", &foo::action)
    ;
}

亲爱的@Tanner Sansbury,谢谢你的回答。虽然您的解决方案是正确的,但看起来boost实际上创建了对齐的对象。在其他调试之后,我得出结论,.def_readonly(“Identity”,Isometry3d::Identity())违反了对齐,而不是对象分配。我可以通过定义一个全局变量来解决这个问题,将其设置为Identity并将该变量定义为readonly。我不知道为什么会发生这种情况。@Kouroush:这可能是未定义行为的结果。接受其值作为常量引用,并返回临时值。因此,Python对象上的<代码>标识< /Cord>属性访问C++中悬空引用。亲爱的Thaner-SaSbBury,谢谢您的回答。虽然您的解决方案是正确的,但看起来boost实际上创建了对齐的对象。在其他调试之后,我得出结论,.def_readonly(“Identity”,Isometry3d::Identity())违反了对齐,而不是对象分配。我可以通过定义一个全局变量来解决这个问题,将其设置为Identity并将该变量定义为readonly。我不知道为什么会发生这种情况。@Kouroush:这可能是未定义行为的结果。接受其值作为常量引用,并返回临时值。因此,Python对象上的<代码>标识< /代码>属性访问了C++中的悬空引用。我遇到了同样的问题,我想我找到了解决方案。我在这里回答了另一个类似的问题:我有同样的问题,我想我找到了解决办法。我在这里回答了另一个类似的问题:
#include <cstdlib>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>

///  @brief Basic custom allocator.
template <typename T>
class custom_allocator
{
public:
  typedef size_t size_type;
  typedef T*     pointer;
  typedef T      value_type;
public:
  pointer allocate(size_type num, const void* hint = 0)
  {
    std::cout << "custom_allocator::allocate()" << std::endl;
    return reinterpret_cast<pointer>(
      std::malloc(num * sizeof(value_type)));
  }

  void deallocate(pointer p, size_type num)
  {
    std::cout << "custom_allocator::deallocate()" << std::endl;
    std::free(p);
  }
};

/// @brief Example class.
class foo
{
public:
  foo()         { std::cout << "foo()" << std::endl; }
  ~foo()        { std::cout << "~foo()" << std::endl; } 
  void action() { std::cout << "foo::action()" << std::endl; }
};

/// @brief Allocator for foo.
custom_allocator<foo> foo_allocator;

/// @brief Destroy a foo object.
void destroy_foo(foo* p)
{
  p->~foo();                      // Destruct.
  foo_allocator.deallocate(p, 1); // Deallocate.
}

/// @brief Factory function to create a foo object.
boost::shared_ptr<foo> create_foo()
{
  void* memory = foo_allocator.allocate(1); // Allocate.
  return boost::shared_ptr<foo>(
    new (memory) foo(), // Construct in allocated memory.
    &destroy_foo);      // Use custom deleter.
}

BOOST_PYTHON_MODULE(example) {
  namespace python = boost::python;
  // Expose foo, that will be managed by shared_ptr, and transparently
  // constructs the foo via a factory function to allow for a custom
  // deleter to use the custom allocator.
  python::class_<foo, boost::shared_ptr<foo>, 
                 boost::noncopyable>("Foo", python::no_init)
    .def("__init__", python::make_constructor(&create_foo))
    .def("action", &foo::action)
    ;
}
>>> import example
>>> f = example.Foo()
custom_allocator::allocate()
foo()
>>> f.action()
foo::action()
>>> f = None
~foo()
custom_allocator::deallocate()