ABI与std::vector兼容的vb6类型是什么? 我一直在用C++编写DLL,现在我必须从VB6应用程序调用这个DLL。
以下是来自此DLL的代码示例:ABI与std::vector兼容的vb6类型是什么? 我一直在用C++编写DLL,现在我必须从VB6应用程序调用这个DLL。,c++,dll,vb6,stdvector,C++,Dll,Vb6,Stdvector,以下是来自此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;
#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;
};
问题是,为了调用DLL的函数,我不知道vb6类型代表std::vector
注:-我为DLL使用一个向量来添加对象。
-我使用指针是为了使用尽可能少的内存。
-对不起,我的英语根本不是我的母语。
-谢谢你的阅读和帮助 编辑:
-我修复了类型问题(id肯定以NullChar结尾,所以LPSTR应该可以做到这一点)。 -我读了你们的答案,我要感谢你们两位,你们的答案彼此接近,一个主要问题仍然存在。我的DLL肯定需要向容器中添加元素。因此,我想知道我如何才能做到这一点。也许我可以在我的函数中添加一个返回类型,然后使函数能够返回它创建的项(而不是直接将其放入容器中),这样vb6应用程序就可以获取这些项并处理它们,但我不知道如何做到这一点 编辑bis: @Rook:我觉得我可以通过使用新结构来实现这一点。
结构ObjectArrayPointer
{
对象*指针;
大小计数器;
} 然后以这种方式调用我的函数:
void __stdcall DLLFunction (ObjectArrayPointer*);
然后,我将能够添加对象并编辑VB6应用程序的“大小”参数,以查找这些新对象。这就是你的意思吗?< /P> < P>你不能这么做,因为它是C++类/模板。在内部,它是一个数组,但不是用VB6创建的方式 最好的方法是更改函数以接受指向带有count参数的数组的指针 您还需要非常小心类型的结构
int
s是Long
sId
字符串将不兼容。VB6将有一个指向Unicode BString的指针(除非你使它固定长度),因为C++中有STD::String,它是ANSI字符数组。若您传递一个对象数组(而不是指针),VB6可能会封送此无论如何,您不应该尝试从DLL导出模板容器。当面对较新的编译器和库时,它们很可能会崩溃(例如,在C++03下构建的库不能很好地处理使用C++11构建的代码) 最简单的方法是接受一个指向缓冲区的指针和一个长度参数
void __stdcall DLLFunction (Object* buffer, size_t nObjects);
如果容器的大小在执行期间不会更改。这个接口非常简单,任何理解C调用约定的语言(例如,几乎每种语言)都可以轻松访问它
您已经放弃了对std::vector的大部分使用,因为您已经将它专门用于对象
;你可以考虑一路创建你自己的<代码> ObjtCopys<代码>类,它使用了<代码> 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_collection CreateObjectCollection(){返回新的object_collection_t;}
void DestroyObjectCollect(object_collection集合){delete collection;}
void AddObjectToCollection(对象\集合集合,对象*对象)
{
收集->对象。推回(对象);
}
//等
所有的模板代码都隐藏起来了,给您留下了一个相当干净和简单的界面,这个界面提供了一个不透明的指针类型,可以由外部代码传递,但只能由您自己查询和修改,等等
编辑:顺便说一句,我在上面的代码中使用了Object*
。只使用普通的对象
可能更安全、更简单,并避免与内存管理和客户端代码的指针操作相关的所有问题。如果对象
足够小和简单,则通过值传递可能是更好的方法
(注意:未检查可编译性或功能。E&OE。警告实施者!)VB6 ABI是COM自动化ABI
因此,如果您需要与VB6 ABI兼容的arry,您可能应该使用SAFEARRAY。我建议您也应该使用编译器COM支持类:
使用ATL的CComSafeArray类,此问题似乎完全符合您的要求:
您可能还想看看这些:
安全阵列的替代方案
SAFEARRAY的替代方案是提供COM集合对象。这只是一个COM对象,具有Dispinterface或具有方法Count
和Item
的双接口。项应具有dispid=0作为默认方法。您可能还希望为\u NewEnum
提供DISPID\u NewEnum
以支持For Each语法。您可能会发现VB6结构中的整数类型需要长
Integer
在VB6中仅为16位。更糟糕的是,std::string是一个字符数组,即ANSI字符串,而BString是Unicode。感谢您的回复,但如上所述,我需要找到一种向输入中添加元素的方法,这就是为什么我在搜索另一种输入类型而不是简单数组。我只是编辑了我的问题,以确保我理解您的意思。@Illmess:从您的编辑:是的,您可以只使用一个包含长度的简单结构,但您依赖的是客户端代码,而不是完全错误的结构。通过像我这样包装std::vector,您不需要信任VB端来获得正确的长度。您所要担心的就是内存释放。您还可以使用std的所有良好特性
// 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