Suppose I have the following simple struct:
struct Vector3
{
double x;
double y;
double z;
};
and I create a list of vertices:
std::vector<Vector3> verticesList;
In addition to this I need to use a third-party library. The library has a function with the following signature:
typedef double[3] Real3;
external void createMesh(const Real3* vertices, const size_t verticesCount);
What is the best way to convert verticesList into something which could be passed into createMesh() as the vertices parameter?
At the moment I use the following approach:
static const size_t MAX_VERTICES = 1024;
if (verticesList.size() > MAX_VERTICES)
throw std::exception("Number of vertices is too big");
Real3 rawVertices[MAX_VERTICES];
for (size_t vertexInd = 0; vertexInd < verticesList.size(); ++vertexInd)
{
const Vector3& vertex = verticesList[vertexInd];
rawVertices[vertexInd][0] = vertex.x;
rawVertices[vertexInd][1] = vertex.y;
rawVertices[vertexInd][2] = vertex.z;
}
createMesh(rawVertices, verticesList.size());
But surely it is not the best way to solve the issue.
That is one proper way of doing it. There are also some other ways…
The type
Vector3is layout compatible with the typeReal3, the implication of this is that you can force casting a pointer to one type to a pointer of the other:Other alternative, as Rook mentions, to remove the loop is using
memcpy, since the types are POD:This is more concise, and probably more efficient, but it still is copying the whole container.
I believe that the standard does guarantee this behavior (at least C++11), two standard layout and standard compatible types have the same memory layout (duh?), and §9.2p19 states:
This guarantee technically means something slightly different than what I claimed before: you can
reinterpret_cast<double*>(&verticesList[0])points toverticesList[0].x. But it also implies that the conversion fromdouble*toReal3pointer through reinterpret cast will also be fine.