【问题标题】:Using Generic TList with Interfaces in C++Builder在 C++Builder 中使用带有接口的通用 TList
【发布时间】:2021-02-15 16:42:13
【问题描述】:

如何在 C++Builder 中创建接口实例列表?我正在尝试以下方法,但编译器以不同的方式抱怨其中的每一种:

#include <System.Generics.Collections.hpp>
...
TList__1<IInterface> IntfList;
TList__1<_di_IInterface> IntfList;
TList__1<DelphiInterface<IInterface>> IntfList;

另一方面,我也无法生成包含对象的列表。

TList__1<TObject> ObjList = new TList__1<TObject>();

所以我很迷茫,看来,文档也无济于事

http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Generics.Collections.TList

或者有没有更好的替代方法?最终,我需要一个数组,但我想使用Add 动态构建它,然后从IntfList-&gt;ToArray() 获取它。

【问题讨论】:

    标签: generics c++builder


    【解决方案1】:

    首先,TList&lt;T&gt; 是 Delphi 的 TObject 派生类,因此它必须在 C++ 中通过 new 动态创建,例如:

    TList__1<T> *MyList = new TList__1<T>;
    ...
    delete MyList;
    

    其中T 可以是_di_IInterfaceTObject*(注意*)等

    现在,话虽这么说......

    如何在 C++Builder 中创建接口实例列表?

    简而言之,你不能在纯 C++ 代码中单独使用 TList&lt;T&gt; 来做到这一点。这是记录在案的行为:

    How to Handle Delphi Generics in C++

    Delphi 泛型作为模板暴露给 C++。然而,重要的是要意识到实例化发生在 Delphi 端,而不是在 C++ 中。因此,您只能将这些模板用于在 Delphi 代码中显式实例化的类型

    ...

    如果 C++ 代码尝试对未在 Delphi 中实例化的类型使用 Delphi 泛型,您将在链接时收到错误

    在原生 RTL 或 VCL/FMX 框架中没有 TList&lt;IInterface&gt; 的默认实例化。因此,您必须将自己的 Delphi 代码添加到您的 C++Builder 项目中才能创建这样的实例化,例如:

    MyTListInstantiationUnit.pas

    unit MyTListInstantiationUnit;
    
    interface
    
    {$HPPEMIT '#pragma link "MyTListInstantiationUnit"'} 
    
    // or in XE5 Update 2 and later:
    // {$HPPEMIT LINKUNIT}
    
    implementation
    
    uses
      System.Generics.Collections;
    
    initialization
      TList<IInterface>.Create.Free;
    finalization
    
    end.
    

    MyCppUnit.cpp

    #include <System.Generics.Collections.hpp>
    #include "MyTListInstantiationUnit.hpp"
    ...
    TList__1<_di_IInterface> *IntfList = new TList__1<_di_IInterface>; // should work now
    

    否则,您可以改用TInterfaceList

    #include <System.Classes.hpp>
    ...
    TInterfaceList *IntfList = new TInterfaceList;
    ...
    delete IntfList;
    

    或者,如果您真的不需要跨 C++/Delphi 边界传递接口列表,则可以考虑使用像 std::vector 这样的纯 C++ 容器,例如:

    #include <vector>
    ...
    std::vector<_di_IInterface> IntfList;
    

    至于TList&lt;TObject&gt;,它确实存在于本机Delphi RTL 中,但它不适合你,只是因为你没有正确使用它。它需要看起来更像这样:

    TList__1<TObject*> *ObjList = new TList__1<TObject*>;
    ...
    delete ObjList;
    

    否则,您可以使用TObjectList 代替,例如:

    #include <System.Contnrs.hpp>
    ...
    TObjectList *ObjList = new TObjectList;
    ...
    delete ObjList;
    

    或者,直接使用std::vector&lt;TObject*&gt;

    【讨论】:

    • 感谢@RemyLebeau,我真的在为我们的Delphi 库使用C++ 示例而苦苦挣扎,诸如此类的各种问题都出现了,我对此一无所知。这解释了它,我希望 TList 的文档也指向那篇文章。 - 所以我的 Delphi 类需要一个 DynamicArray - 如果我没看错的话,除了从前面的数组开始之外,没有巧妙的方法来构造它?
    • @JouniAro 您不需要 TList 即可使用 DynamicArray。它们是完全不同的东西。但是是的,如果你需要传入一个DynamicArray,那么你必须根据需要构造和填充它,例如:DynamicArray&lt;_di_IMyInterface&gt; arr; arr.Length = ...; /* fill arr ... */ MyComponent-&gt;DoSomething(arr);
    • 是的,我当然知道。 TList 只是在不预先定义长度的情况下更方便地填充。这就是为什么我一直在尝试复制的 Delphi 示例中使用它。但我不会这样做。 Tx 用于清除此问题。
    • @JouniAro "TList 只是在不预先定义长度的情况下更方便地填充" - 除非您需要与 Delphi 代码交互,否则我只会使用 std::vector .
    • 是的,这是与 Delphi 组件交互的示例代码,因此它需要一个 DynamicArray。是否有任何简单的方法可以将 std-types 转换为 Delphi(?) 类型,例如 std::vector 到 DynamicArray?我猜 DynamicArray 是 Delphi 类型,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-08
    • 2014-02-09
    相关资源
    最近更新 更多