【问题标题】:Define an interface in C++ that needs to be implemented in C# and C++在 C++ 中定义一个需要在 C# 和 C++ 中实现的接口
【发布时间】:2008-09-15 16:52:59
【问题描述】:

我有一个在 C++ 中定义的接口,现在需要在 C# 中实现。解决此问题的最佳方法是什么?我根本不想在我的接口定义中使用 COM。我现在解决这个问题的方法是有两个接口定义,一个在 C++ 中,一个在 C# 中。然后我将 C# 接口公开为 COM 服务器。这是我用 C++ 编写的应用程序,可以调用 C#。无论如何我可以避免在 C++ 和 C# 中定义我的实现吗?

【问题讨论】:

    标签: c# .net c++ interop interface


    【解决方案1】:

    如果您愿意将 C++/CLI 用于托管代码而不是 C#,那么您可以直接通过头文件使用本机 C++ 接口定义。这将是多么容易将取决于您的界面中的确切内容 - 最简单的情况是您可以从 C 中使用。

    查看 Marcus Heege 的 Expert C++/CLI: .NET for Visual C++ Programmers,了解有关在 .NET 中混合原生 C++ 和托管 C++ 的许多有用信息。

    【讨论】:

    • 还想在这里补充一点,Nishant Sivakumar 的 C++/CLI in Action 是了解如何将 C++ 连接到 C# 的绝佳资源。
    【解决方案2】:

    Swig 是用于将 C++ 类包装成其他语言(如 C#)的绝佳工具。

    【讨论】:

      【解决方案3】:

      你为什么不想使用 COM?

      这本来是我的建议。 COM 互操作对我来说工作得非常好,我在 C# 中使用了 COM 对象和接口(只需引用 COM 对象,运行时可调用包装器就会自动创建)。同样,将 C# 类标记为“注册 COM 互操作”也有相反的效果。

      【讨论】:

        【解决方案4】:

        用 C++ 编写接口并使用宏使其看起来像 UNIX 上的标准 cpp 头文件和 Windows 上的 IDL 文件(如果这不起作用,您可以随时编写 python/ruby 脚本来生成C++ 头文件中的 IDL)。

        编译 IDL 以生成类型库。使用 TypeLib Importer 为 C# 生成接口定义并在那里实现接口。

        【讨论】:

          【解决方案5】:

          另一种方法是使用“平面”的 C 风格 API。您不妨使用extern "C" 来防止意外过载。使用 DEF 文件显式命名导出的函数,因此绝对不会以任何方式修饰它们(C++ 函数使用导出表中参数类型的编码进行“修饰”)。

          在 x86 上,请注意调用约定。可能是明确声明使用__stdcall__cdecl。因为 P/Invoke 主要用于调用 Windows API,所以它默认为 StdCall,但 C 和 C++ 默认为 cdecl,因为它支持可变参数。

          我最近将 COM 接口 IRapiStream 包装在一个平面 C 接口中,因为 .NET 似乎试图将 IStream 转换为存储,但失败并出现错误 STG_E_UNIMPLEMENTEDFUNCTION

          【讨论】:

            【解决方案6】:

            您没有提及您使用的是哪个版本的 .NET,但在使用 Visual Studio .NET 2003 时对我有用的是为真正的 C++ 类的 pimpled 实现提供一个精简的 C# 包装器:

            public __gc class MyClass_Net {
            public:
               MyClass_Net()
                  :native_ptr_(new MyClass())
               {
               }
               ~MyClass_Net()
               {
                  delete native_ptr_;
               }
            
            private:
               MyClass __nogc *native_ptr_;
            };
            

            显然,人们更愿意在那里使用 Boost shared_ptr,但我永远无法让它们与 V.NET 2003 很好地配合...

            方法只是通过指针转发到底层 C++ 方法。可能必须转换方法参数。例如,要调用采用字符串的 C++ 方法,C# 方法可能应该采用 System.String(托管 C++ 中的 System::String)。你必须使用 System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi() 来做到这一点。

            这种方法的一个好处是因为托管 C++ 是一种 .NET 语言,您可以将访问器公开为属性 (__property)。您甚至可以公开属性,就像在 C# 中一样。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-01
              • 1970-01-01
              • 1970-01-01
              • 2011-03-17
              • 1970-01-01
              相关资源
              最近更新 更多