如何使用 boost.python 公开对齐的类

2024-02-10

当尝试像这样公开对齐的类时:

class __declspec(align(16)) foo
{
public:
    void foo_method() {}
};

BOOST_PYTHON_MODULE(foo_module)
{
    class_<foo>("foo")
        .def("foo_method", &foo::foo_method);
}

你最终会遇到错误(msvs 2010):

error C2719: 'unnamed-parameter': formal parameter with __declspec(align('16')) won't be aligned,
see reference to class template instantiation 'boost::python::converter::as_to_python_function<T,ToPython>' being compiled

到目前为止我找到的解决方案是使用智能指针来存储对象:

BOOST_PYTHON_MODULE(foo_module)
{
    class_<foo, boost::shared_ptr<foo>, boost::noncopyable>("foo")
        .def("foo_method", &foo::foo_method);
}

难道就没有更好的解决办法吗?这非常烦人,因为您应该包装所有按值返回对象的函数以返回智能指针,并且性能也会降低。


我遇到了同样的问题,想要一个不涉及shared_ptr的解决方案。它涉及专门化一些 boost::python 类,以确保我们获得足够大的存储区域,以便能够在其中对齐我们的对象。

我写了一篇有点长的博客文章解释我是如何得出这个解决方案的here http://fhtagn.net/prog/2015/04/16/quaternion_boost_python.html。以下是我找到的解决方案。我觉得这是一个很大的黑客,所以也许它会破坏其他东西。但到目前为止seems去工作,我还没有找到更好的东西。

我试图公开 Eigen::Quaternionf (需要 16 字节对齐):

bp::class_<Quaternionf>("Quaternion", bp::init<float, float, float, float>())
  .def(bp::init<Matrix3f>())
  .add_property("w", get_prop_const(&Quaternionf::w))
  .add_property("x", get_prop_const(&Quaternionf::x))
  .add_property("y", get_prop_const(&Quaternionf::y))
  .add_property("z", get_prop_const(&Quaternionf::z))
  .def("matrix", &Quaternionf::matrix)
  .def("rotvec", &quaternion_to_rotvec);

该解决方案涉及专门化 3 个类:

boost::python::对象::实例请求比我们的类型需要的多 16 个字节,以确保我们可以对齐

...
union
{
    align_t align;
    char bytes[sizeof(Data) + 16];
} storage;
...

boost::python::objects::make_instance_impl正确设置实例的 Py_SIZE

...
Holder* holder = Derived::construct(
  &instance->storage, (PyObject*)instance, x);
holder->install(raw_result);

// Note the position of the internally-stored Holder,
// for the sake of destruction
// Since the holder not necessarily allocated at the start of
// storage (to respect alignment), we have to add the holder
// offset relative to storage
size_t holder_offset = reinterpret_cast<size_t>(holder)
                        - reinterpret_cast<size_t>(&instance->storage)
                        + offsetof(instance_t, storage);
Py_SIZE(instance) = holder_offset;
...

boost::python::objects::make_instance这样构造方法就会在存储中对齐持有者

...
static inline QuaternionfHolder* construct(void* storage, PyObject* instance, reference_wrapper<Quaternionf const> x)
{
  // From the specialized make_instance_impl above, we are guaranteed to
  // be able to align our storage
  void* aligned_storage = reinterpret_cast<void*>(
    (reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
  QuaternionfHolder* new_holder = new (aligned_storage) 
    QuaternionfHolder(instance, x);
  return new_holder;
}
...

完整代码如下:

typedef bp::objects::value_holder<Eigen::Quaternionf> QuaternionfHolder;

namespace boost { namespace python { namespace objects {

using namespace Eigen;

//template <class Data = char>
template<>
struct instance<QuaternionfHolder>
{
  typedef QuaternionfHolder Data;
    PyObject_VAR_HEAD
    PyObject* dict;
    PyObject* weakrefs;
    instance_holder* objects;

    typedef typename type_with_alignment<
        ::boost::alignment_of<Data>::value
    >::type align_t;

    union
    {
        align_t align;
        char bytes[sizeof(Data) + 16];
    } storage;
};


// Adapted from boost/python/object/make_instance.hpp

//template <class T, class Holder, class Derived>
template<class Derived>
struct make_instance_impl<Quaternionf, QuaternionfHolder, Derived>
{
    typedef Quaternionf T;
    typedef QuaternionfHolder Holder;

    typedef objects::instance<Holder> instance_t;

    template <class Arg>
    static inline PyObject* execute(Arg& x)
    {
        BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));

        PyTypeObject* type = Derived::get_class_object(x);

        if (type == 0)
            return python::detail::none();

        PyObject* raw_result = type->tp_alloc(
            type, objects::additional_instance_size<Holder>::value);

        if (raw_result != 0)
        {
            python::detail::decref_guard protect(raw_result);

            instance_t* instance = (instance_t*)raw_result;

            // construct the new C++ object and install the pointer
            // in the Python object.
            //Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result);
            Holder* holder = Derived::construct(
                &instance->storage, (PyObject*)instance, x);
            holder->install(raw_result);

            // Note the position of the internally-stored Holder,
            // for the sake of destruction
            // Since the holder not necessarily allocated at the start of
            // storage (to respect alignment), we have to add the holder
            // offset relative to storage
            size_t holder_offset = reinterpret_cast<size_t>(holder)
                                 - reinterpret_cast<size_t>(&instance->storage)
                                 + offsetof(instance_t, storage);
            Py_SIZE(instance) = holder_offset;

            // Release ownership of the python object
            protect.cancel();
        }
        return raw_result;
    }
};


//template <class T, class Holder>
template<>
struct make_instance<Quaternionf, QuaternionfHolder>
    : make_instance_impl<Quaternionf, QuaternionfHolder, make_instance<Quaternionf,QuaternionfHolder> >
{
    template <class U>
    static inline PyTypeObject* get_class_object(U&)
    {
        return converter::registered<Quaternionf>::converters.get_class_object();
    }

    static inline QuaternionfHolder* construct(void* storage, PyObject* instance, reference_wrapper<Quaternionf const> x)
    {
      LOG(INFO) << "Into make_instance";
      LOG(INFO) << "storage : " << storage;
      LOG(INFO) << "&x : " << x.get_pointer();
      LOG(INFO) << "&x alignment (0 = aligned): " << (reinterpret_cast<size_t>(x.get_pointer()) & 0xf);

      // From the specialized make_instance_impl above, we are guaranteed to
      // be able to align our storage
      void* aligned_storage = reinterpret_cast<void*>(
          (reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
      QuaternionfHolder* new_holder = new (aligned_storage) QuaternionfHolder(instance, x);
      LOG(INFO) << "&new_holder : " << new_holder;
      return new_holder;
      //return new (storage) QuaternionfHolder(instance, x);
    }
};


}}} // namespace boost::python::objects
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 boost.python 公开对齐的类 的相关文章

  • 到底什么是“对齐指针”?

    有人可以告诉我什么是对齐指针实际上意味着什么 这意味着所指向的地址可以被某个因子整除 有时使用术语 自然对齐 这通常意味着具有自然对齐的对象需要放置在可被对象大小整除的地址处 对齐有时非常重要 因为许多与硬件相关的事物都对这种对齐设置了限制
  • 无法在 OS X 上链接到 Boost.Python

    我正在尝试使用 Boost Python 构建一个非常简单的示例 我已经用自制软件安装了 boost 和 boost python 我正在使用 python 3 4 3 和 boost 1 59 我的操作系统是 El Capitan Boo
  • 为什么需要内存对齐?

    我知道这个问题已经被问过一千次了 我已经阅读了每一个答案 但我仍然不明白 我的 RAM 模型可能存在一些根本性错误 使我无法理解任何答案 我从互联网上得到了所有这些小信息 但我就是无法将它们联系起来 以下是我认为到目前为止所知道的 以 IA
  • 如何将 asyncio 与 boost.python 一起使用?

    可以用Python3吗asyncio封装有Boost Python图书馆 I have CPython C 构建的扩展Boost Python 以及编写的函数C 可以工作很长时间 我想用asyncio调用这些函数但是res await cp
  • 为什么在 boost python 向量索引套件中需要比较运算符?

    我想公开 C 代码 std vector a 到蟒蛇 我的 class A 没有实现比较运算符 当我尝试时 BOOST PYTHON MODULE libmyvec using namespace boost python class a
  • Boost.Python.ArgumentError:python str 未转换为 std::string

    我收到一个错误 我无法理解尝试通过 Boost Python 包装一个相当简单的 C 类的意义 一 班级 include
  • 无法加载 Boost.Python 模块 - 未定义的符号

    我有一个用 C 编写的库 需要从 Python 访问 所以我使用 Boost Python 包装它 我可以毫无问题地将我的库编译成 Boost so 文件 但是当我尝试将其加载到 Python 中时 使用import tropmodboos
  • 物理内存的对齐是如何保证的?

    malloc 返回适合任何内置类型的内存 如果需要更具体的对齐 例如 16 或 32 字节 可以在应用程序级别完成 但这种对齐是在虚拟内存级别 如何保证底层物理内存也处于相同的对齐方式 虚拟内存是在页面级别实现的 因此每个虚拟机页面在加载到
  • 公开 C++ 函数,使用 Boost.Python 返回指针

    我想使用 Boost Python 将以下 C 函数公开给 Python int test1 return new int 42 Now exposing the function with Boost Python BOOST PYTHO
  • C++ 中的原子性:神话还是现实 [重复]

    这个问题在这里已经有答案了 我读过一篇关于无锁编程 http msdn microsoft com en us library ee418650 28v vs 85 29 aspx在 MSDN 中 它说 在所有现代处理器上 您可以 假设读取
  • 迭代 boost::python vector_indexing_suite 出现意外结果

    我已经成功包装了一个名为 Composite 的类 这个类有以下方法 std vector
  • 无法在 python 中导入自定义 DLL

    我正在尝试将 C 类公开给 pythonboost python 所以我正在经历本教程 http www boost org doc libs 1 61 0 libs python doc html tutorial tutorial ex
  • Pickling boost python 函数

    为了与 joblib Parallel 一起使用 我需要能够 pickle boost python 函数 当我尝试这样做时 我得到了 TypeError can t pickle builtin function or method ob
  • 使用 boost.python 在 cygwin 中手动构建 python 扩展

    很抱歉这么笼统的标题 但我不太确定我到底错过了什么或我做错了什么 我的目标是在 cygwin 下使用 boost python 构建一个 python 扩展 并避免使用 boost build 工具 即使用 make 而不是 bjam 后一
  • 为什么需要内存对齐? [复制]

    这个问题在这里已经有答案了 可能的重复 内存对齐的目的 https stackoverflow com questions 381244 purpose of memory alignment 我在网上读了一些关于内存对齐的文章 可以理解
  • 将Python脚本添加到C++项目中

    我如何将用 python 编写的脚本添加到 c 项目中 谢谢 编辑 基本上 脚本所做的只是通过电子邮件发送一些数据 我想将数据和电子邮件地址传递给用 python 编写的函数 希望这能说明问题 你可以看看Boost Python http
  • 关于 Hinnant 堆栈分配器的问题

    我一直在使用霍华德辛南特的堆栈分配器 http howardhinnant github io stack alloc h它的工作方式就像一个魅力 但实施的一些细节对我来说有点不清楚 为什么全球运营商new and delete用过的 这a
  • 为什么对齐是2的幂?

    有一句话来自参考参数 http en cppreference com w cpp language object Alignment 每个对象类型都具有称为对齐要求的属性 该属性 是一个整数值 std size t 类型 始终是 2 的幂
  • 对齐静态字符串文字

    我有一个静态结构数组 struct CommandStruct char data unsigned ans size static const CommandStruct commands Some literal 28 Some oth
  • 对于所有对象类型 T 来说,sizeof(T) >=alignof(T) 总是这样吗?

    对于任何对象类型T是不是总是这样sizeof T 至少与alignof T 直观上似乎是这样 因为即使您调整对象的对齐方式 例如 struct small char c 高于通常的情况 它们的 大小 也会向上调整 以便数组中的对象之间的关系

随机推荐

  • 作为参数传递的函数总是回调吗? JavaScript

    如果我有下面的代码 我将两个函数作为参数传递给函数sayHi 这是回调的示例吗 我注意到有两种运行这些 参数函数 的方法 要么如下所示 我们在定义它们的地方调用函数 作为参数 要么在 sayHi 函数中调用参数 这是回调函数和匿名函数之间的
  • Rails - capistrano 和 chmod

    我想通过 capistrano 使用 chmod 来添加文件夹的权限 例如 我想这样做 chmod 777 R vol www apps ror tutorial current log 所以 我想通过 capistrano 的任务来做到这
  • Android - 如何在 API 级别 4 的 android WebViewClient 中拦截表单 POST

    我有一个WebViewClient附在我的WebView像这样 webView setWebViewClient new MyWebViewClient 这是我的实现MyWebViewClient private class MyWebVi
  • 使用curl命令行上传多个文件到php服务器

    我需要使用curl 命令行实用程序将多个文件上传到服务器 对于单个文件 我使用以下命令没有问题 curl F email protected cdn cgi l email protection http localhost 8888 we
  • 寻找非图灵完备的语言

    我知道一点什么是a图灵机 questions tagged turing machine and a 图灵完备 questions tagged turing complete语言 但为了更好地理解 有人可以举出非图灵完备的语言的例子吗 甚
  • Java拖动图像更好&重叠图像检测

    我有两个问题要问你 已解决 在java中 我能够使用鼠标侦听器在图像中移动 如果我单击并向上移动鼠标 它只会向上移动图像 而不是将图像精确移动到指针所在的位置 不让图像跳转到我的鼠标指针所在的位置 已解决 由于我正在构建一个编辑器 如果窗口
  • getopt.h:在 Windows 中编译 Linux C 代码

    我正在尝试获取一组九个 c 文件 以及九个相关的 h 文件 在 Windows 下进行编译 该代码最初是在 Linux 中设计的 用于使用标准 GNU Linux C 库 getopt h 获取命令行参数 该库不适用于在 Windows 中
  • JS:给定二维数组中的一个点和一个距离,哪些坐标是可移动的?

    给定一个任意大小的二维数组 如下所示 var board 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  • 如何在 paypal 沙箱中获取身份令牌?

    我不知道 paypal 沙盒上的身份令牌在哪里 身份令牌与 api 编号相同吗 通过 www sandbox paypal com 访问个人资料 然后转至https www sandbox paypal com businessmanage
  • NoClassDefFoundError是如何抛出的

    我在 eclipse 中构建了一个名为 com hello 的包 并编写了一个简单的 HelloWorld 程序 Eclipse 自动添加了 package com hello 在我的程序之上 并且HelloWorld java被放入 F
  • python-将用户输入转换为整数格式时遇到问题

    user input Enter a number and I will tell you the sum of the multiples of 3 and 5 leading up to it number int user input
  • Apache HttpClient 4.1 - 代理身份验证

    我一直在尝试使用 Apache HttpComponent 的 httpclient 时从配置的属性配置代理身份验证的用户和密码 但没有成功 我发现的所有示例都引用了不再可用的方法和类 例如HttpState and setProxyCre
  • 如何观察 Vue.js 组件中 prop 的变化?

    我将图像文件路径数组传递给组件 我想知道如果我传递不同的数组 在 Vue js 组件中观察 prop 更改的最佳方式是什么 我正在使用引导轮播 所以想在数组更改时将其重置为第一个图像 为了简单起见 我将代码示例简化为 Vue compone
  • Chrome 如何检测信用卡字段?

    在某些表单中 Chrome 自动填充会提示信用卡自动填充 编辑 添加屏幕截图 这与浏览器自动完成不同 您之前不必以相同的形式输入该值 我应该如何编写 HTML 表单 以便浏览器将其检测为信用卡字段并触发此行为 与 Stripe 表单一起使用
  • 从 SVG 矩形元素获取每个像素的 RGB 值

    我需要获取 svg 矩形元素中每个像素的颜色值 在 canvas 中我们可以通过方法 getImageData x y width height 获取它 在svg中 有什么方法可以做到这一点吗 如果是的话请给出一些工作示例 如果您创建一个独
  • 从 Wordpress 创建关联数组 $wpdb->get_results

    这是漫长的一天 出于某种原因 这完全让我无法理解 我的 WordPress 数据库请求如下所示 results wpdb gt get results sql 输出看起来像这样 Array 0 gt stdClass Object id g
  • 选择默认值后,Android Complete 操作会继续显示

    我在应用程序开发中遇到了一个奇怪的问题 在我的应用程序中的某个时刻 它会调用 Intent Intent ACTION SEND 来启动 Gmail 将出现 使用 完成操作 对话框 即使我选中底部的默认框并选择 Gmail 下次我的应用程序
  • 离子电容器:错误:未在网络上实现

    完成迁移后cordova to capacitor 运行时出现以下错误ionic s Error vendor js 114293 ERROR Error Uncaught in promise Error Not implemented
  • 找不到类“android.support.v4.widget.SwipeRefreshLayout”[重复]

    这个问题在这里已经有答案了 我不断收到此错误 它导致我的应用程序崩溃 尝试实现新的 v4 滑动刷新布局 我已经更新了支持库 sdk 问题是什么 找不到类 android support v4 widget SwipeRefreshLayou
  • 如何使用 boost.python 公开对齐的类

    当尝试像这样公开对齐的类时 class declspec align 16 foo public void foo method BOOST PYTHON MODULE foo module class