Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert an array of doubles to an array of structs with only double members without copying data

I am using a third-party C++ library to do some heavy lifting in Julia. On the Julia side, data is stored in an object of type Array{Float64, 2} (this is roughly similar to a 2D array of doubles). I can pass this to C++ using a pointer to a double. On the C++ side, however, data is stored in a struct called vector3:

typedef struct _vector3
{
    double x, y, z;
} vector3;

My quick and dirty approach is a five-step process:

  1. Dynamically allocate an array of structs on the C++ side
  2. Copy input data from double* to vector3*
  3. Do heavy lifting
  4. Copy output data from vector3* to double*
  5. Delete dynamically allocated arrays

Copying large amounts of data is very inefficient. Is there some arcane trickery I can use to avoid copying data from double to struct and back? I want to somehow interpret a 1D array of double (with a size that is a multiple of 3) as a 1D array of a struct with 3 double members.

like image 709
mtgoncalves Avatar asked Jul 16 '18 07:07

mtgoncalves


2 Answers

Unfortunately no you cannot. And this is because of the aliasing rule that C++ has. In short if you have an object T you cannot legally access it from a pointer of incompatible type U. In this sense you cannot access an object of type double or double* via a pointer of type struct _vector3 or vice-versa.

If you dig deep enough you will find reinterpret_cast and maybe think "Oh this is exactly what I need" but it is not. No matter what trickery you do (reinterpret_cast or otherwise) to bypass the language restrictions (also known as just make it compile) the fact remains that you can legally access the object of type double only via pointers of type double.

One trick that is often used to type-pune is to use union. Legal in C it is however illegal in C++ but some compilers allow it. In your case however I don't think there is a way to use union.

The ideal situation would be to do the heavy lifting on the double* data directly. If that is feasible on your workflow.

like image 139
bolov Avatar answered Sep 23 '22 05:09

bolov


Strictly speaking, you cannot. I asked a similar question some times ago (Aliasing struct and array the C++ way), and answers explained why direct aliasing would invoke Undefined Behaviour, and gave some hints on possible workarounds.

That being said you are already in a corner case, because the original data come from a different language. That means that the processing of that data is not covered by the C++ standard and is only defined by the implementation that you are using (gcc/version or clang/version or...)

For your implementation, it might be legal to alias an external array to a C++ struct or an external struct to a C++ array. You shuld carefully the documentation of mixed language programming for your precise implementation.

like image 43
Serge Ballesta Avatar answered Sep 21 '22 05:09

Serge Ballesta