在C++中定义一个需要在C#和C++中实现的接口
题
我有一个在 C++ 中定义的接口,现在需要在 C# 中实现。解决这个问题的最佳方法是什么?我根本不想在接口定义中使用 COM。我现在解决这个问题的方法是有两个接口定义,一个在 C++ 中,一个在 C# 中。然后,我将 C# 接口公开为 COM 服务器。这是我用 C++ 编写的应用程序,可以调用 C#。无论如何,我是否可以避免在 C++ 和 C# 中定义我的实现?
解决方案
如果您愿意对托管代码使用 C++/CLI 而不是 C#,那么您可以直接通过头文件使用本机 C++ 接口定义。这有多容易将取决于您的界面中的内容 - 最简单的情况是您可以从 C 中使用。
看看马库斯·希吉的 专家 C++/CLI:面向 Visual C++ 程序员的 .NET, ,了解有关在 .NET 中混合本机 C++ 和托管 C++ 的大量有用信息。
其他提示
痛饮 是一个用 C# 等其他语言包装 C++ 类的好工具。
为什么不想使用COM?
这是我的建议。COM 互操作对我来说非常有效,并且我在 C# 中使用了 COM 对象和接口(只需引用 COM 对象,运行时可调用包装器就会自动创建)。同样,将 C# 类标记为“注册 COM 互操作”也有相反的效果。
用 C++ 编写接口并使用宏使其看起来像 UNIX 上的标准 cpp 头文件和 Windows 上的 IDL 文件(如果这不起作用,您始终可以编写一个 python/ruby 脚本来从C++ 头文件)。
编译 IDL 以生成类型库。使用 TypeLib Importer 生成 C# 的接口定义并在那里实现接口。
用IDL编写接口并使用工具将接口编译为目标语言。在研究涉及跨语言接口的 CORBA 时,您可能会找到这方面的指示。
/艾伦
另一种方法是使用“扁平”的 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
.
您没有提及您正在使用哪个版本的 .NET,但是在使用 Visual Studio .NET 2003 时对我有用的东西是为真正的 C++ 类的粗糙实现提供一个薄的 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# 中一样。