COM - 在C ++中使用IEnumerable

时间:2017-04-10 10:11:54

标签: 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

我错过了什么?

谢谢,

2 个答案:

答案 0 :(得分:1)

你是如何得出那个C ++代码还不是很清楚,你通常使用#import指令来导入C#项目生成的类型库。哪个应该类似:

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

假设C#项目名称为&#34; CSharpLibrary&#34;。这会生成从_com_ptr_t派生的智能指针类型,它们与附加Ptr的接口具有相同的名称。这样做的好处是可以处理引用计数,并且使用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#接口公开IEnumerator而不是IEnumerable来避免对GetEnumerator()的额外调用,如链接问题中所述。您可以在this MSDN article中阅读有关此处使用的C ++编译器支持类的更多信息。

答案 1 :(得分:0)

尝试公开您的DbReader.GetUsers(...)实施,以便正确实施IDbReader界面。例如:

internal class DbReader : IDbReader
{
    public IEnumerable GetUsers() => new List<string>() { "User1", "User2" };
}

除C#代码中的using System.CollectionsIEnumerable)外,还要确保using System.Collections.Generic(对于List<T>)。