【问题标题】:Calling C# From Unmanaged C++ Passing Or Returning "Complex" Types从非托管 C++ 调用 C# 传递或返回“复杂”类型
【发布时间】:2011-01-24 13:04:27
【问题描述】:

我正在寻求有关如何使用复杂对象作为返回值或作为参数传递给作为 COM 组件暴露给非托管 C++ 的 C# 类方法的帮助

原因如下:

我正在处理一个项目,我们有六个非托管 C++ 应用程序,每个应用程序都直接访问同一个 Microsoft SQL Server 数据库。我们希望能够以最少的更改使用 MS-Sql/Oracle/MySql,我们决定实现业务逻辑和通过 WCF 服务公开的数据层以获得所需的灵活性。

此策略取决于能否让非托管 C++ 与 WCF 服务互操作。有很多方法可以做到这一点,但我要遵循的策略是创建一个作为 COM 组件公开的 C# 程序集,它将充当 C++ 和 WCF 层之间的桥梁。此 C# 程序集将作为 COM 组件加载到非托管 C++ 进程中。

C# 桥程序集将包含一个帮助器类,该类具有许多描述以前在 C++ 代码中表示为直接 sql 或存储 proc 调用的操作的方法。

我有两个问题要解决

1) 对于 INSERT,我需要传递一个表示要插入的实体的对象。在非托管 C++ 方面,我已经知道其中一个实体有大约 40 个属性必须将其放入 SQL 中——我不想要具有 40 个参数的 C# 方法,我想传递一个对象;我不知道如何通过 COM 将 C++ 对象编组到 C# 中,所以我考虑在 C# 端定义一个 Stuct,然后使 Struct COM 可见。

2) 如何返回“SELECT this, that, other, ...”的结果。我见过两个例子。一个返回一个 struct[],另一个返回一个结构,其中包含每个列字段的 string[] 和一个描述其他成员数组长度的 int count 成员。

在 C# 方面,我认为这将是定义和公开许多请求/响应结构的情况,这些结构将用于传入/传出数据。这些结构需要用属性进行修饰,使其成员不会因为优化而“改变位置”。并且结构成员可能需要使用向编组器提示该成员应如何在 COM 中公开的属性进行修饰。

当然,我必须弄清楚如何从非托管 C++ 中将这些结构作为 COM 对象实例化和填充,然后我必须在方法调用中传递它们并将它们作为返回值处理。

这对我来说是最困难的部分;我了解 C++ 和一些 MFC/ATL,但 C++ 下的 COM 是一个额外的复杂级别。任何推荐的关于参数传递和返回值处理主题的书籍、博客和教程都会非常有帮助。

【问题讨论】:

    标签: c# c++ com interop marshalling


    【解决方案1】:

    如果可能的话,我会避免将 COM 引入图片中。如果您控制 C++ 代码(听起来像您这样做),添加一个调用 C# 代码的单个 C++/CLI cpp 文件应该更容易。 C++/CLI 可以直接访问和创建托管和非托管类型并在它们之间进行复制。

    【讨论】:

    • 绝对是个好主意。如果出于某种原因您不想将所有 C++ 代码编译为 C++/CLI,您甚至可以在导出非托管函数/类的单独 DLL 中创建 C++/CLI 代码。您确实放松了 .NET COM 代码为您提供的自动编组,但您也避开了很多潜在的麻烦。
    • 是的,我可以控制 C++ 代码。我尝试在项目级别打开 clr 支持,但收到一条错误消息,指出 /MTd 和 /clr 开关不兼容。这就是我选择 COM 路线的原因,因为我可以让 C++ 几乎保持不变,除非我在调用 CoInitialize 时遇到其他错误。如果我要创建一个 C++/CLI DLL,我会不会处于相同的位置?即必须导出它的内容。如何将 C++/CLI dll 添加到当前似乎不使用 COM 的非托管 C++ 应用程序?
    • /MTd 表示 C++ 运行时库的静态链接,确实与 C++/CLI 不兼容。如果你将它们链接为 DLL,你会没事的。您不需要将所有代码编译为 C++/CLI。相反,在项目级别启用它,并禁用所有文件,除了必须与 .net 对话的新文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    相关资源
    最近更新 更多