ABI与std::vector兼容的vb6类型是什么? 我一直在用C++编写DLL,现在我必须从VB6应用程序调用这个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;

以下是来自此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;
};
问题是,为了调用DLL的函数,我不知道vb6类型代表std::vector

注:
-我为DLL使用一个向量来添加对象。
-我使用指针是为了使用尽可能少的内存。
-对不起,我的英语根本不是我的母语。
-谢谢你的阅读和帮助

编辑:
-我修复了类型问题(id肯定以NullChar结尾,所以LPSTR应该可以做到这一点)。 -我读了你们的答案,我要感谢你们两位,你们的答案彼此接近,一个主要问题仍然存在。我的DLL肯定需要向容器中添加元素。因此,我想知道我如何才能做到这一点。也许我可以在我的函数中添加一个返回类型,然后使函数能够返回它创建的项(而不是直接将其放入容器中),这样vb6应用程序就可以获取这些项并处理它们,但我不知道如何做到这一点

编辑bis:

@Rook:我觉得我可以通过使用新结构来实现这一点。
结构ObjectArrayPointer
{
对象*指针;
大小计数器;
}

然后以这种方式调用我的函数:

void __stdcall DLLFunction (ObjectArrayPointer*);

然后,我将能够添加对象并编辑VB6应用程序的“大小”参数,以查找这些新对象。这就是你的意思吗?< /P> < P>你不能这么做,因为它是C++类/模板。在内部,它是一个数组,但不是用VB6创建的方式

最好的方法是更改函数以接受指向带有count参数的数组的指针

您还需要非常小心类型的结构

  • 在VB6中,C++
    int
    s是
    Long
    s
  • 另外,
    Id
    字符串将不兼容。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