在C ++ IDL中定义一个结构,然后在C#中适当地使用MarshalAs()

时间:2012-08-17 21:01:45

标签: c# c++ struct com-interop idl

我有一个C ++ COM服务器,用数据填充C#调用者的结构。

结构在C ++ IDL中定义,如下所示:

interface Icontrol : IDispatch{
    [ 
    uuid(...), 
    version(1.0) ]
    typedef struct testStructure
    { 
        int x;
        int y;
        int z;
        ...
    } testStructure; 

    ...
    [id(9)] HRESULT getStruct([ref,in,out] testStructure * theData);
    ...

然后,在C#代码中:

EO_Lib.testStructure test = new EO_Lib.testStructure();
EO_Lib.getStruct(ref test);

我可以通过简单地在C#结构中使用MarshallAs来为C#的非本地字段使这个工作成为常规.DLL的问题。但我不能让它在COM .DLL上工作。我怀疑这是因为我对IDL缺乏了解。

我需要做的是使用我用适当的MarshallAs()信息创建的新C#类型调用getStruct()。我该怎么做?

我正在使用Visual Studio 2010 MFC / ATL C ++和C#.NET 4 Framework,如果有帮助的话。

2 个答案:

答案 0 :(得分:0)

虽然不是问题的实际解决方案,但以下是我的问题的原因。

来自:http://msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.100).aspx

从平台调用调用返回的结构必须是blittable类型。平台调用不支持非blittable结构作为返回类型。

基本上,你不能做我想做的事。

如果忽略COM方面,BrokenGlass的解决方案 here 会回答转换一个结构到另一个问题。

答案 1 :(得分:0)

听起来你正试图从管理方面解决这个问题。不知道很多关于你的架构的细节(比如这是你的COM服务器,就像你编写它/拥有代码一样?)我将不得不做出一些假设,以便提供从C ++方面接近的任何解决方案,特别是MIDL(IDL)方面。

您提到了IDL,据我所知,您至少可以访问生成类型库的IDL。因此,忘记CLR(托管)方面的内容,并将其全部用于非托管环境(COM)。

完成后,确定您希望结构体对受管客户端的外观。使用该信息,在C ++ / MIDL项目中定义新类型。如果您没有IDL的ACF(应用程序配置文件)文件,请创建一个(它只是一个具有完全相同名称的IDL文件,但带有" .acf"扩展名而不是&# 34; .idl"。在ACF文件中声明一个user_marshal类型,它将您的COM结构映射到您刚刚定义的新的"托管友好"结构。像这样:

// ACF file

typedef [user_marshal(testStructure_ForDotNet)] testStructure;

// where testStructure is your "original" struct and "testStructure_ForDotNet" 
// is the one you just defined.

最后,您需要定义转换函数(封送处理函数)。有关更多信息,请参阅此资源:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa367296(v=vs.85).aspx

无论如何,希望有所帮助(任何人)。