我有一个我在C ++中定义的接口,现在需要在C#中实现。最好的方法是什么?我不想在我的接口定义中使用COM。我现在解决这个问题的方法是有两个接口定义,一个是C ++,另一个是C#。然后我将C#接口公开为COM服务器。这是我用C ++编写的应用程序可以调用C#。无论如何,我可以避免在C ++和C#中定义我的实现吗?
答案 0 :(得分:4)
如果您愿意将C ++ / CLI用于托管代码而不是C#,那么您可以直接通过头文件使用本机C ++接口定义。这将是多么容易取决于你的界面到底是什么 - 最简单的情况是你可以从C使用。
查看Marcus Heege的Expert C++/CLI: .NET for Visual C++ Programmers,了解有关在.NET中混合本机和托管C ++的大量有用信息。
答案 1 :(得分:2)
Swig是一个很好的工具,可以用C#等其他语言包装C ++类。
答案 2 :(得分:1)
为什么不想使用COM?
这可能是我的建议。 COM interop对我来说非常好用,我在C#中使用了COM对象和接口(只需引用COM对象,并自动创建运行时可调用包装器)。类似地将C#类标记为“为COM互操作注册”已经反过来了。
答案 3 :(得分:1)
用C ++编写接口并使用宏使它看起来像UNIX上的标准cpp头文件,就像Windows上的IDL文件一样(如果这不起作用,你总是可以写一个python / ruby脚本来生成来自C ++头文件的IDL。)
编译IDL以生成类型库。使用TypeLib Importer生成C#的接口定义并在那里实现接口。
答案 4 :(得分:1)
在IDL中编写接口并使用工具将接口编译为目标语言。在研究与跨语言接口有关的CORBA时,您可能会发现这一点。
/阿伦
答案 5 :(得分:1)
另一种方法是使用'扁平',C风格的API。您也可以使用extern "C"
来防止意外超载。使用DEF文件显式命名导出的函数,因此它们绝对不会以任何方式进行修饰(C ++函数在导出表中使用参数类型的编码进行“修饰”)。
在x86上,注意调用约定。它可能是明确声明使用__stdcall
或__cdecl
。因为P / Invoke主要用于调用Windows API,所以默认为StdCall,但C和C ++默认为cdecl,因为它支持varargs。
我最近将COM接口IRapiStream
包装在一个扁平的C接口中,因为.NET似乎试图将IStream转换为存储,但失败时出现错误STG_E_UNIMPLEMENTEDFUNCTION
。
答案 6 :(得分:0)
你没有提到你正在使用哪个版本的.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(Managed C ++中的System :: String)。你必须使用System :: Runtime :: InteropServices :: Marshal :: StringToHGlobalAnsi()来做到这一点。
这种方法的一个好处是因为托管C ++是一种.NET语言,您可以将访问器公开为属性(__property)。您甚至可以公开属性,就像在C#中一样。