5

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

4

6 回答 6

4

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

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

于 2008-09-15T17:33:46.673 回答
2

Swig是一个很好的工具,可以用其他语言(如 C#)包装 C++ 类。

于 2008-09-18T03:48:54.727 回答
1

你为什么不想使用COM?

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

于 2008-09-15T17:02:01.290 回答
1

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

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

于 2008-09-15T18:06:54.643 回答
1

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

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

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

于 2008-09-15T23:18:41.710 回答
0

您没有提及您使用的是哪个版本的 .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# 中一样公开属性。

于 2008-09-15T21:01:28.063 回答