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?
将verticesList转换为可以作为顶点参数传递给createMesh()的内容的最佳方法是什么?
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.
但这肯定不是解决问题的最佳方式。
1 个解决方案
#1
5
That is one proper way of doing it. There are also some other ways...
这是一种正确的做法。还有其他一些方法……
The type Vector3
is layout compatible with the type Real3
, the implication of this is that you can force casting a pointer to one type to a pointer of the other:
Vector3类型的布局与Real3类型兼容,其含义是您可以强制将指针转换为一种类型到另一种类型的指针:
createMesh( reinterpret_cast<Real3*>(&verticesList[0]), vertices.size() );
Other alternative, as Rook mentions, to remove the loop is using memcpy
, since the types are POD:
Rook提到的其他方法是使用memcpy来删除循环,因为这些类型是POD:
Real3 rawVertices[MAX_VERTICES];
std::memcpy( rawVertices, &verticesList[0],
vertices.size()*sizeof verticesList[0] );
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:
我相信这个标准并保证这种行为(至少c++ 11),两个标准布局和标准兼容的类型有相同的内存布局(咄?),和§9.2 p19状态:
A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.
指向标准布局结构体对象的指针,适当地使用reinterpretation t_cast转换,指向它的初始成员(或者如果该成员是位字段,那么指向它所在的单元),反之亦然。
This guarantee technically means something slightly different than what I claimed before: you can reinterpret_cast<double*>(&verticesList[0])
points to verticesList[0].x
. But it also implies that the conversion from double*
to Real3
pointer through reinterpret cast will also be fine.
这个保证在技术上意味着与我之前声明的略有不同:您可以重新解释t_cast
#1
5
That is one proper way of doing it. There are also some other ways...
这是一种正确的做法。还有其他一些方法……
The type Vector3
is layout compatible with the type Real3
, the implication of this is that you can force casting a pointer to one type to a pointer of the other:
Vector3类型的布局与Real3类型兼容,其含义是您可以强制将指针转换为一种类型到另一种类型的指针:
createMesh( reinterpret_cast<Real3*>(&verticesList[0]), vertices.size() );
Other alternative, as Rook mentions, to remove the loop is using memcpy
, since the types are POD:
Rook提到的其他方法是使用memcpy来删除循环,因为这些类型是POD:
Real3 rawVertices[MAX_VERTICES];
std::memcpy( rawVertices, &verticesList[0],
vertices.size()*sizeof verticesList[0] );
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:
我相信这个标准并保证这种行为(至少c++ 11),两个标准布局和标准兼容的类型有相同的内存布局(咄?),和§9.2 p19状态:
A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.
指向标准布局结构体对象的指针,适当地使用reinterpretation t_cast转换,指向它的初始成员(或者如果该成员是位字段,那么指向它所在的单元),反之亦然。
This guarantee technically means something slightly different than what I claimed before: you can reinterpret_cast<double*>(&verticesList[0])
points to verticesList[0].x
. But it also implies that the conversion from double*
to Real3
pointer through reinterpret cast will also be fine.
这个保证在技术上意味着与我之前声明的略有不同:您可以重新解释t_cast