如何通过 COM 互操作将字符串集合从 C# 返回到 C++ [英] How to return a collection of strings from C# to C++ via COM interop

查看:23
本文介绍了如何通过 COM 互操作将字符串集合从 C# 返回到 C++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 C# 中为某些 Display 方法创建了一个 com 组件,它返回一个字符串列表

如下图.在 v++ 中,我使用 std::lst 来捕获 Disp() 的返回值,但它

给出 Disp 不是类成员的编译器错误.我将返回类型设为 s void 然后

它工作正常.我可以修改什么,以便 Disp 返回一个列表,而在 main(c++) 中我必须使用

这个返回值.

公共接口ITest{列表<字符串>显示();}类 TestLib:ITest{列表<字符串>显示(){列表<字符串>li=new List();li.Add("堆栈");li.Add("结束");li.Add("流量");回礼;}}

成功编译并创建了 Test.dll 以及 test.tlb.现在在用 C++ 编写的 main 函数中

#include#import "..	est.tlb"使用命名空间测试;无效主(){HRESULT hr=CoInitialize(null);ITestPtr Ip(__uuidof(TestLib));std::list<字符串>li=new std::list();li=Ip->Disp();}

当我尝试编译它时我的代码有什么问题

<块引用>

'Disp': 不是 TestLib:ITest 的成员

如何解决这个问题,请帮帮我....当我让它在 Class 中返回类型为 void 时它工作正常.我犯了什么错误????

解决方案

即使您修正了拼写错误,这也行不通.COM 互操作没有从 List 到 COM 中的东西的标准映射,它当然不会将它映射到 std::list.泛型不允许出现在 COM 接口中.

更新

我尝试使用 ArrayList 作为返回类型,因为它是非通用的,我认为 tlb 可能会包含它的类型信息.那没有用,所以我尝试了 IList.这也不起作用(#import 语句生成了一个 .tlh 文件,该文件引用了 IList 但没有对其进行定义.)

作为一种解决方法,我尝试声明一个简单的列表接口.代码最终是这样的:

[Guid("7366fe1c-d84f-4241-b27d-8b1b6072af92")]公共接口 IStringCollection{int计数{得到;}字符串获取(整数索引);}[指南(8e8df55f-a90c-4a07-bee5-575104105e1d")]公共接口 IMyThing{IStringCollection GetListOfStrings();}公共类 StringCollection : List, IStringCollection{公共字符串获取(整数索引){返回这个[索引];}}公共课 Class1 : IMyThing{公共 IStringCollection GetListOfStrings(){return new StringCollection { "Hello", "World" };}}

所以我有我自己的(非常简单的)字符串集合接口.请注意,我的 StringCollection 类不必定义 Count 属性,因为它从 List 继承了一个非常好的属性.>

然后我在 C++ 方面有这个:

#include "stdafx.h"#import "..ClassLibrary5.tlb"#include <向量>#include <字符串>使用命名空间 ClassLibrary5;int _tmain(int argc, _TCHAR* argv[]){CoInitialize(0);IMyThingPtr 东西(__uuidof(Class1));std::vector字符串向量;IStringCollectionPtr strings(thing->GetListOfStrings());for (int n = 0; n GetCount(); n++){const char *pStr = 字符串->Get(n);vectorOfStrings.push_back(pStr);}返回0;}

我必须手动将字符串集合的内容复制到适当的 C++ 标准容器中,但它可以工作.

可能有一种方法可以从标准集合类中获取正确的类型信息,因此您不必制作自己的集合接口,但如果没有,这应该没问题.

或者,您是否看过 C++/CLI?虽然它仍然不会自动将 CLR 集合转换为 std 容器,但它会非常无缝地工作.

I hav created a com componet for some Display method in C# it returns a String List

as shown below. In v++ i hav used std::lst to catch the return value from Disp() but it

gives compiler error that Disp is not a member of class. I i make return type a s void then

it works fine. what i can modify so that Disp return a List and in main(c++) i have to use

this return value.

Public interface ITest
{
    List<string> Disp();
}

class TestLib:ITest
{
    List<string> Disp()
    {
        List<string> li=new List<string>();
        li.Add("stack");
        li.Add("over");
        li.Add("Flow");

        return li;
    }
}

compiled and created Test.dll successfully and also test.tlb. Now in main function that is written in c++

#include<list>
#import "..	est.tlb"
using namespace Test;
void main()
{
    HRESULT hr=CoInitialize(null);

    ITestPtr Ip(__uuidof(TestLib));

    std::list<string> li=new std::list<string>();

    li=Ip->Disp();
}

What's wrong in my code when i try to compile this it shows

'Disp':is not a member of TestLib:ITest

how to solve this plz help me ....when i make it return type as void in Class it works fine .what mistake i did????

解决方案

This just isn't going to work, even if you fix the typos. COM interop doesn't have a standard mapping from List<T> to something in COM, and it certainly won't map it to std::list. Generics aren't allowed to appear in COM interfaces.

UPDATE

I tried using ArrayList as the return type, as that's non-generic I thought maybe the tlb would include type information for it. That didn't work so I tried IList. That didn't work either (the #import statement produced a .tlh file that referred to IList but had not definition for it.)

So as a workaround I tried declaring a simple list interface. The code ends up like this:

[Guid("7366fe1c-d84f-4241-b27d-8b1b6072af92")]
public interface IStringCollection
{
    int Count { get; }
    string Get(int index);
}

[Guid("8e8df55f-a90c-4a07-bee5-575104105e1d")]
public interface IMyThing
{
    IStringCollection GetListOfStrings();
}

public class StringCollection : List<string>, IStringCollection
{
    public string Get(int index)
    {
        return this[index];
    }
}

public class Class1 : IMyThing
{
    public IStringCollection GetListOfStrings()
    {
        return new StringCollection { "Hello", "World" };
    }
}

So I have my own (very simplistic) string collection interface. Note that my StringCollection class doesn't have to define the Count property because it inherits a perfectly good on from List<string>.

Then I have this on the C++ side:

#include "stdafx.h"
#import "..ClassLibrary5.tlb"

#include <vector>
#include <string>

using namespace ClassLibrary5;

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(0);

    IMyThingPtr thing(__uuidof(Class1));

    std::vector<std::string> vectorOfStrings;

    IStringCollectionPtr strings(thing->GetListOfStrings());
    for (int n = 0; n < strings->GetCount(); n++)
    {
        const char *pStr = strings->Get(n);
        vectorOfStrings.push_back(pStr);
    }

    return 0;
}

I have to manually copy the contents of the string collection a proper C++ standard container, but it works.

There may be a way to get proper type info from the standard collection classes, so you don't have to make your own collection interfaces, but if not, this should serve okay.

Alternatively, have you looked at C++/CLI? That would work pretty seamlessly, although it still wouldn't convert CLR collections to std containers automatically.

这篇关于如何通过 COM 互操作将字符串集合从 C# 返回到 C++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆