在 Qt 信号和槽函数中将固定大小的 Eigen 类型作为参数传递

pass fixed-size Eigen types as parameters in Qt signals and slots function

这是与 Qt 论坛重复的 post:Qt forum thread

我需要在 Qt 信号和槽函数中传递一个 fixed-size vectorizable Eigen types。 请注意,信号和相应的槽函数在需要 QueuedConnection 的不同线程中是 运行。因此,信号函数中传递的参数被复制。详情请看这个link

Qt 声​​明参数可以通过值或 const 引用传递,信号槽将根据连接类型 (QueuedConnection/DirectConnection) 决定是否需要复制。

但是,Eigen 声明 Eigen 对象必须通过引用传递,否则它是非法的或者程序可能会崩溃(在我的例子中:我遇到了对齐问题的编译错误)。有关更多详细信息,请参阅此处:link

如果我通过 const 引用传递 Eigen 对象并在信号槽的 connect() 之前使用 qRegisterMetaType() 注册 Eigen 对象,我也会遇到编译错误。错误看起来像: __declspec(align(‘16’)) 的实际参数不会对齐

我还写了一个包装器 class,其中包含根据要求 here 的 Eigen 对象。不幸的是,同样的错误。

我的环境:Win7 64bit – VS2010 – Qt 5.3.1 – Eigen 3.2.4

有人在 Qt signals-slots 函数中将 Eigen 对象作为参数传递了吗?你是怎么做到的。

更新(添加 SSCCE): 如果你想克隆自己,我把它放在要点上: https://gist.github.com/f8af655a238ec136dbe9.git

// main.cpp
#include <QCoreApplication>
#include "A.h"
#include "B.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    A obj_a;
    B obj_b;

    qRegisterMetaType<eigen_wrapper>("eigen_wrapper");
    QObject::connect(&obj_a, &A::send, &obj_b, &B::receive);

    return a.exec();
}

// A.h
#pragma once

#include <QObject>
#include "eigen_wrapper.h"


class A : public QObject
{
    Q_OBJECT

private:
    eigen_wrapper eigen_object;

signals:
    // signal
    void send(const eigen_wrapper &);
};


// B.h
#pragma once
#include <QObject>
#include "eigen_wrapper.h"


class B : public QObject
{

    Q_OBJECT

private:
    eigen_wrapper eigen_object;

    public slots:

        inline void receive (const eigen_wrapper &s)
        {
            eigen_object = s;
        }
};


// eigen_wrapper.h
#pragma once
#include "Eigen/Dense"

class eigen_wrapper
{
    Eigen::Vector3f vec;
    Eigen::Quaternionf quat;

public:
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

编译错误:

2>ClCompile: 2> main.cpp 2>C:\Qt\Qt5.3.1.3\msvc2010_opengl\include\QtCore/qobjectdefs_impl.h(573): error C2718: 'const eigen_wrapper': actual parameter with __declspec(align('16')) won't be aligned 2> C:\Qt\Qt5.3.1.3\msvc2010_opengl\include\QtCore/qobjectdefs_impl.h(588) : see reference to class template instantiation 'QtPrivate::AreArgumentsCompatible' being compiled 2>
with 2> [ 2> A1=eigen_wrapper, 2>
A2=eigen_wrapper 2> ] 2>
c:\qt\qt5.3.1.3\msvc2010_opengl\include\qtcore\qobject.h(228) : see reference to class template instantiation 'QtPrivate::CheckCompatibleArguments' being compiled 2>
with 2> [ 2> List1=QtPrivate::List, 2> List2=QtPrivate::List 2> ] 2> ..\main.cpp(14) : see reference to function template instantiation 'QMetaObject::Connection QObject::connect(const A *,Func1,const B ,Func2,Qt::ConnectionType)' being compiled 2> with 2> [ 2> Func1=void (__thiscall A:: )(const eigen_wrapper &), 2> Func2=void (__thiscall B::* )(const eigen_wrapper &) 2> ] 2> 2>Build FAILED.

非常感谢, 林

根据持续数年的错误讨论: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=83

他们在以下环境中测试 Eigen: - MSVC9、MSVC10、MSVC11,在 x64 中 -> 有效(错误未显示) - MSVC11 x32 -> 有效。 - MSVC9、MSVC10,在 x32 中 -> 失败。

作为解决方法,我将

#define EIGEN_DONT_ALIGN_STATICALLY

在任何包含 Eigen 之前 header。

代码现在可以编译并且 运行 正确。