This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Mixin Eigen wrappers

Tags: None
(comma "," separated)
User avatar
enisbayramoglu
Registered Member
Posts
4
Karma
0

Mixin Eigen wrappers

Sat Sep 08, 2012 3:36 pm
Hi everyone, I'm a long time user of Eigen (and loving it as well!) but a first time poster here, so forgive me if I'm doing something wrong.

I've recently needed to wrap a C library in C++. The library has a struct called orxVector that it uses very often. It's simply a vector of 3 float dimensions. In my C++ wrapper, I've decided to wrap it, so that it can be used in Eigen expressions while retaining the ability to use the wrapper class where an orxVector is needed. The solution I've come up with involves Eigen::Map:

Code: Select all
typedef Eigen::Matrix<orxFLOAT,3,1> VectorType;
typedef Eigen::Map<VectorType> Mapping;
class OVector: public orxVECTOR, public Mapping {
public:
    OVector():orxVECTOR(), Mapping(reinterpret_cast<orxFLOAT *>(static_cast<orxVECTOR*>(this))) {}
    OVector(orxFLOAT x, orxFLOAT y, orxFLOAT z):
        orxVECTOR(),
        Mapping(reinterpret_cast<orxFLOAT *>(static_cast<orxVECTOR*>(this))) {
            fX = x; fY=y, fZ=z;
        }
    OVector(const VectorType & other):Mapping(reinterpret_cast<orxFLOAT *>(static_cast<orxVECTOR*>(this))) {
        Mapping::operator=(other);
    }

    OVector(const OVector & other): Mapping(reinterpret_cast<orxFLOAT *>(static_cast<orxVECTOR*>(this))) {
       Mapping::operator=(other);
    }
};


Now this works exactly as I intend it to. It can be passed to functions that expect orxVector *, and it can also be used in expressions like OVector * Matrix3f. The problem with this approach is that it introduces an unnecessary bloat in the memory footprint. It must also have a performance hit since there's an extra layer of indirection while accessing the vector as an Eigen vector through the map.

The ideal solution for me would be to have a mixin type, that looks like:

Code: Select all
typedef Eigen::MixinWrapper<Eigen::Matrix<orxFLOAT,3,1>,orxVECTOR> WrappedVector;


Where WrappedVector inherits from orxVECTOR, so it's usable in any context that orxVECTOR is used, can be used as an Eigen::Matrix<orxFLOAT,3,1>, has no unnecessary memory footprint bloat or indirections for member access.

I've actually achieved this through a very, Very, VERY dirty method. I have:
- copied the forward declarations of Map and MapBase, the contents of MapBase.h and the contents of Map.h into a file called MixinWrapper.h
- I've replaced Map, MapBase with MixinWrapper, MixinWrapperBase
- Made these classes accept an extra second argument called "Wrappee"
- made MixinWrapperBase inherit from Wrappee as the first base
- replaced m_data occurrences with reinterpret_cast<Scalar *>(this) (or const Scalar * where needed)
- Changed the Map specialization of traits to MixinWrapper
- Possibly 1-2 other minor changes

Here's the resulting file: pancarsoft.com/MixinWrapper.hpp (I have Eigen version 3.0.5)

Now this surprisingly works!

On to the question: What do you think about my "solution", how many days will it be, before this class stops working (with new Eigen versions)? Is there a less dirty way of achieving this?

Thanks!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Mixin Eigen wrappers  Topic is solved

Sat Sep 08, 2012 7:55 pm
I cannot read pancarsoft.com/MixinWrapper.hpp, but what you would have to do is:

class OVector: public orxVECTOR, public MatrixBase<OVector>

and make OVector Eigen compatible by:

- make Eigen::internal::traits<OVector> inherits Eigen::internal::traits<Eigen::Vector3f>
- implement rows(), cols(), coeff(i) and coeffRef(i) in OVector (maybe also coeff(i,j) and coeffRef(i,j), not sure)
- put the following in the class body:

typedef MatrixBase<OVector> Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(OVector)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(OVector)

and that's all.
User avatar
enisbayramoglu
Registered Member
Posts
4
Karma
0

Re: Mixin Eigen wrappers

Sun Sep 09, 2012 11:03 am
That's much nicer (and surely much more future-proof) than what I've done. Thanks! :)

BTW, a small side-question, is it safe to use anything in the internal namespace in your code? I'd assume that anything that goes in the internal namespace is subject to change even in minor version changes.

Cheers!


Bookmarks



Who is online

Registered users: Baidu [Spider], Bing [Bot], Google [Bot], Yahoo [Bot]