c++ - COM - 在 C++ 中使用 IEnumerable

标签 c++ com

我正在尝试公开一个返回 IEnumerable 的方法,但我无法通过 C++ 代码使用它。我读了this SO问题,但它是关于 IEnumerator 而不是 IEnumerable

[ComVisible(true),
    Guid("myguid")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IDbReader
{
    IEnumerable GetUsers();
}

[ComVisible(true),
    Guid("myguid2")]
[ProgId("MyDbReader.DbReader")]
internal class DbReader : IDbReader
{
    IEnumerable GetUsers() => new List<string>() { "User1", "User2" };
}

在 C++ 中:

#import "MyDbReader.tlb" named_guids raw_interfaces_only

...

CComPtr<IDbReader> myreader; // created through a factory
CComPtr<IEnumerable> users;
myreader->GetUsers(&users);

users->GetEnumerator(); // The compiler says: pointer to incomplete class is not allowed 

此外,编译器会看到 IDbReader::IEnumerable 而不是使用标准的 IEnumerable

我错过了什么?

谢谢,

最佳答案

不太清楚您是如何获得该 C++ 代码的,您通常会使用 #import 指令导入 C# 项目生成的类型库。应该类似于:

#import "c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.tlb"
using namespace mscorlib;
#import "CSharpLibrary.tlb"
using namespace CSharpLibrary;

假设 C# 项目名称是“CSharpLibrary”。这会生成从 _com_ptr_t 派生的智能指针类型,它们与附加了 Ptr 的接口(interface)同名。优点是引用计数得到处理,接口(interface)函数调用失败通过 C++ 异常报告,而不是难以处理的 HRESULT 错误代码。

额外的细节,确实很难从不稳定的编译错误消息中诊断出来,但从 IntelliSense 中可以看到,是 .NET 类型库导出器将 System.Collections.IEnumerator 转换为 IEnumVARIANT*。所以基本代码应该是这样的:

try {
    IEnumerablePtr users = myreader->GetUsers();
    IEnumVARIANTPtr enumusers = users->GetEnumerator();
    _variant_t vuser;
    while (SUCCEEDED(enumusers->Next(1, &vuser, NULL))) {
        BSTR user = vuser.bstrVal;
        // etc...
    }
}
catch (_com_error& ex) {
    // Handle or report runtime error...
}

未经测试,应该在大概范围内。您可以通过让 C# 接口(interface)公开 IEnumerator 而不是 IEnumerable 来避免对 GetEnumerator() 的额外调用,如链接问题中所述。您可以在 this MSDN article 中阅读更多有关此处使用的 C++ 编译器支持类的信息。 .

关于c++ - COM - 在 C++ 中使用 IEnumerable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43320450/

相关文章:

c++ - 使用 CRTP 强制显式模板实例化

c++ - _bstr_t 到 char 指针并调用 atof(...)

command-line - 如何使用 vbc 命令行编译器(无 IDE)像 shdocvw 一样引用 COM 库?

delphi - Delphi COM 对象中的早期绑定(bind)和后期绑定(bind)在性能方面哪个更好

c# - Excel DNA - 在回调中将 C# 字符串编码到 VBA ByRef

c++ - 为什么我会得到对任何与打印相关的函数 win32 的 undefined reference ?

c++ - 使用 Boost.Build 和 Boost.Test - 链接器错误

c++ - CoRegisterClassObject 破坏线程安全

c++ - 警告 : No Previous Declaration - C++

c++ - 如何在 Qt C++ 中为数组动态分配内存?