跨 DLL 边界暴露 std::vector - 编译器无关最佳实践

7
在DLL边界上公开STL容器不是一个好主意,通常也不可能(详见此答案以了解原因,以及有关在DLL边界上公开std::list的这篇文章)。我需要能够在使用不同编译器(VC08 / VC10+)编译的DLL和EXE之间传递数据; 这个问题只处理一切都相同的情况。
最佳的公开方式是什么?向量与列表有点不同,因为内存保证是连续的,因此如果我只需要一个const double向量,则可以将开始和结束指针提供给dll中的函数以获取块。 DLL还需要返回一些结构,例如向量数组。
我想到了一个包含开始和结束指针的结构:
template <typename T>
struct vecWrapper<T> {
    T*  begin;
    T*  end;
}

// in the dll
int func(vecWrapper<double> numbers);

这样做是否明智?假设从函数返回的任何内容都需要一个析构函数(在dll端)来销毁它所指向的东西。


2
相关,请阅读:https://dev59.com/x2035IYBdhLWcg3wC7YR#5664491 - John Dibling
感谢@JohnDibling,这是一个很好的解释,说明为什么不直接暴露STL容器。因此问题在于如何公开数据本身。我希望连续要求可以使它在没有进一步复制的情况下成为可能。 - Phil H
为什么不直接传递一个普通的数组呢? - Rook
@Rook:因为我更愿意在构建和处理的每一侧使用STL,只有在跨越边界时才会转向指针等。如果在堆上使用数组,则相当于传递开始和结束指针(如我在问题中考虑的那样),因此我不知道有什么收益。在堆栈上传递...我不知道。 - Phil H
1个回答

3
你已经很好地理解了。标准要求向量元素在内存中是连续的,除非你在使用向量的分配器进行游戏,否则向量元素不会被堆叠分配,因此始终可以将向量的数据表示为起始和结束指针(或开始指针和大小,如果您需要的话)。您所拥有的应该可以正常工作。
然而,我不确定这有多大用处。std :: vector除了自动内存管理之外,实际上并没有为您提供任何东西,并且您不希望那样做;否则,当销毁DLL中构造的任何向量时,将释放原始double数组。您可以通过复制数组来避免这种情况,但是您已经说过您不想这样做。STL算法可以在指针上正常工作,因此可能没有必要在DLL中进行转换。

它确实为我提供了在调用代码和被调用代码中本地声明的向量内的自动内存管理,包括返回向量,我想。因此,传递到dll中的向量将在超出范围时自动销毁,当其析构函数被调用时(在dll内部)。 - Phil H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接