哪种 vb6 类型与 std::vector 兼容 BIB
What vb6 type is ABI-compatible with std::vector?
我一直在用C++编写一个DLL,现在我必须从VB6应用程序调用这个DLL。
下面是此 DLL 中的代码示例:
#include <vector>
#include <string>
using namespace std;
void __stdcall DLLFunction (vector<Object>*)
{
// performs a few operations on the Objects contained in the vector.
}
struct Object
{
long CoordX;
long CoordY;
long Width;
long Height;
LPSTR Id;
};
我还在 VB6 中定义了"对象结构"
Private Type Object
CoordX As Integer
CoordY As Integer
Width As Integer
Height As Integer
Id As String
End Type
问题是我不知道什么 vb6 类型可以代表 std::vector 以调用 DLL 的函数。
笔记:
- 我使用 DLL 的向量来添加对象。
- 我使用指针是为了使用尽可能少的内存。
- 对不起我的英语,它根本不是我的母语。
- 感谢您的阅读并试图帮助我。
编辑:
- 我修复了键入问题(Id 肯定由 NullChar 结束,所以 LPSTR 应该可以解决问题)。- 我读了你们的答案,我要感谢你们俩,你们的答案彼此接近,一个主要问题仍然存在。我的 DLL 肯定需要将元素添加到容器中。因此,我想知道如何做到这一点。也许我可以向我的函数添加一个返回类型,然后使函数能够返回它创建的项目(而不是直接将其放入容器中),以便 vb6 应用程序获取这些项目并能够处理它们,但我无法弄清楚如何做到这一点
编辑之二 :
@Rook :我觉得我可以通过使用新的结构来实现这一点。
struct ObjectArrayPointer
{ 对象* 指针;
size_t计数器;
}
然后这样调用我的函数:
void __stdcall DLLFunction (ObjectArrayPointer*);
然后,我将能够添加对象并编辑 VB6 应用程序的大小参数以查找这些新对象。这是你的意思吗?
您都不应该尝试从 DLL 导出模板容器。当面对较新的编译器和库时,它们可能会中断(例如,在 C++03 下构建的库将无法很好地与使用 C++11 构建的代码配合使用)。
最不痛苦的事情是接受指向缓冲区的指针和长度参数,
void __stdcall DLLFunction (Object* buffer, size_t nObjects);
如果容器的大小在执行过程中不会改变。这个接口非常简单,并且可以通过任何理解 C 调用约定的语言(例如,几乎每一个)轻松访问。
你已经放弃了std::vector
的大部分使用,因为你已经把它专门化Object
;你可以考虑一路走下去,创建你自己的ObjectCollection
类,它在内部使用std::vector
,但提供了一个非模板化的接口。这里有一个简单的例子:
// In your public API header file:
typedef struct object_collection_t *object_collection;
object_collection CreateObjectCollection();
void DestroyObjectCollect(object_collection collection);
void AddObjectToCollection(object_collection collection, Object* object);
// etc
页眉中不会以任何形式公开任何模板类型。这很好。
// And the corresponding code file:
struct object_collection_t
{
std::vector<Object*> objects;
};
object_collection CreateObjectCollection() { return new object_collection_t; }
void DestroyObjectCollect(object_collection collection) { delete collection; }
void AddObjectToCollection(object_collection collection, Object* object)
{
collection->objects.push_back(object);
}
// etc
所有的模板代码都被隐藏起来,给你留下了一个相当干净和简单的界面,它提供了一个不透明的指针类型,可以通过外部代码传递,但只能由你自己的查询和修改,等等。
编辑:顺便说一下,我在上面的代码中使用了Object*
。使用普通的旧Object
并避免与客户端代码的内存管理和指针操作相关的所有问题可能更安全,更麻烦。如果Object
足够小且简单,则按值传递可能是更好的方法。
(注意:未检查可编译性或功能。E&OE。警告实施者!
这样做,因为它是一个C++类/模板。在内部,它是一个数组,但不能以可以从 VB6 创建的方式。
最好的办法是更改函数以接受指向具有 count 参数的数组的指针。
您还需要非常小心类型的结构。
- C++
int
在 VB6 中是Long
s。 - 此外,
Id
字符串将不兼容。VB6 将有一个指向 unicode BString 的指针(除非您将其固定长度),其中作为C++将具有 std::string,它是一个 ANSI 字符数组。 VB6 可能会封送它,如果你传递一个对象数组(而不是指针)
VB6 ABI 是 COM Automation ABI。
因此,如果您需要与VB6 ABI兼容的arry,则可能应该使用SAFEARRAY。我建议你也应该使用编译器COM支持类:
http://msdn.microsoft.com/en-US/library/5yb2sfxk(v=vs.80).aspx
这个问题似乎完全符合您的要求,使用 ATL 的 CComSafeArray 类:
- 标准::矢量和_variant_t之间的转换
您可能还想查看以下内容:
- https://stackoverflow.com/search?q=safearray+_variant_t
安全阵列的替代品
安全阵列的替代方法是提供 COM 集合对象。这只是一个具有 Dispinterface 或双接口的 COM 对象,具有方法 Count
和 Item
。项目应具有 dispid=0 作为默认方法。您可能还希望为_NewEnum
提供DISPID_NEWENUM
以支持 For Each 语法。
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中用vector填充一个简单的动态数组
- vector.resize()中的分配错误
- 使用std::vector的OpenCL矩阵乘法
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 在某些循环内使用vector.push_back时出现分段错误
- 当vector是tje全局变量时,c++中vector的内存管理
- std::vector的包装器,使数组的结构看起来像结构的数组
- 为什么(-1)%vector::size()总是返回0
- 在C++中将类(带有Vector成员)保存为二进制文件
- 编译器如何区分std::vector的构造函数
- 将 int 数组转换为 std::vector<int*>
- 使用 pqxx 将 std::vector 存储在 postgresql 中,并从数据库中检索它
- 在std::vector上存储带有模板的类实例
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 为什么std::vector比数组慢
- std::vector::迭代器是否可以合法地作为指针
- 如何将二进制格式的 C++ 对象的 std::vector 保存到磁盘?
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 哪种 vb6 类型与 std::vector 兼容 BIB