我一直在用 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 的 vector 来添加对象。
- 我使用指针是为了尽可能少地使用内存。
- 对不起我的英语,它根本不是我的母语。
- 感谢您阅读并试图帮助我。
编辑:
- 我修复了打字问题(Id 肯定以 NullChar 结尾,所以 LPSTR 应该可以解决问题)。
- 我读了你们的回答,我要感谢你们两个,你们的答案很接近,但一个主要问题仍然存在。我的 DLL 肯定需要向容器中添加元素。因此,我想知道我该怎么做。也许我可以向我的函数添加一个返回类型,然后使该函数能够返回它创建的项目(而不是直接将其放入容器中),以便 vb6 应用程序获取这些项目并能够处理它们,但是我不知道该怎么做
编辑之二:
@Rook:我觉得我可以通过使用新结构来实现这一目标。
结构 ObjectArrayPointer
{
对象*指针;
size_t 计数器;
}
然后这样调用我的函数:
void __stdcall DLLFunction (ObjectArrayPointer*);
然后我就可以为我的 VB6 应用程序添加对象并编辑大小参数以找到这些新对象。你是这个意思吗?
最佳答案
无论如何,您都不应该尝试从 DLL 中导出模板容器。当面对较新的编译器和库时,它们很可能会崩溃(例如,在 C++03 下构建的库不能很好地与使用 C++11 构建的代码配合使用)。
最不痛苦的事情是接受一个指向缓冲区的指针和一个长度参数,
void __stdcall DLLFunction (Object* buffer, size_t nObjects);
如果容器的大小在执行过程中不会改变。这个接口(interface)非常简单,任何理解 C 调用约定的语言(例如,几乎所有语言)都可以轻松访问它。
您已经放弃了 std::vector
的大部分使用,因为您已经将它特化为 Object
;您可以考虑一路走下去并创建自己的 ObjectCollection
类,该类在内部使用 std::vector
但提供非模板化接口(interface)。这是一个简单的例子:
// 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 类型与 std::vector 兼容 ABI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11222087/