嵌入标准C++;进入.NET应用程序 我想在标准的、平台无关的C++中编写算法库。 我可以接受相同的C++代码,并将其编译为.NET,以便C语言应用程序可以使用该库吗? 如果不是,实现这种互操作的最简单的方法是什么? < P>不能直接在C语言和标准C++之间进行接口。但是,您可以在C++ /CLI包装器中使用C++库,这使得.NET托管代码中的功能可用性(因此C<)。 简单地将包装器写为C++ .CLI库,它公开了.NETAPI并包含了来自标准C++库的代码(但不幸的是,据我所知,这不能静态链接)。您有三种方法来将库暴露为易于从托管代码调用: 为它编写一个C++/CLI包装,其中包含一个公共ref类——C#代码将调用此类的方法,该类将调用库的本机方法 将库中的C风格函数作为DLL公开-C代码将使用P/Invoke调用该函数 在C++中编写一个COM组件,它使用你的库并通过添加一个COM引用来从C代码中调用它。
第三个,COM,我只是为了完整性才加入的。这不是我的第一选择。或者我的第三个。如果COM组件存在是一回事,那么仅仅为此编写它又是另一回事嵌入标准C++;进入.NET应用程序 我想在标准的、平台无关的C++中编写算法库。 我可以接受相同的C++代码,并将其编译为.NET,以便C语言应用程序可以使用该库吗? 如果不是,实现这种互操作的最简单的方法是什么? < P>不能直接在C语言和标准C++之间进行接口。但是,您可以在C++ /CLI包装器中使用C++库,这使得.NET托管代码中的功能可用性(因此C<)。 简单地将包装器写为C++ .CLI库,它公开了.NETAPI并包含了来自标准C++库的代码(但不幸的是,据我所知,这不能静态链接)。您有三种方法来将库暴露为易于从托管代码调用: 为它编写一个C++/CLI包装,其中包含一个公共ref类——C#代码将调用此类的方法,该类将调用库的本机方法 将库中的C风格函数作为DLL公开-C代码将使用P/Invoke调用该函数 在C++中编写一个COM组件,它使用你的库并通过添加一个COM引用来从C代码中调用它。,.net,visual-c++,c++-cli,interop,managed-c++,.net,Visual C++,C++ Cli,Interop,Managed C++,第三个,COM,我只是为了完整性才加入的。这不是我的第一选择。或者我的第三个。如果COM组件存在是一回事,那么仅仅为此编写它又是另一回事 在前两者之间,问题在于还有谁可以使用这个库。如果C#代码是唯一使用它的代码,那么做你喜欢的。但例如,您可能有15或20个本机方法来设置各种属性,然后是执行实际工作的go或execute方法。因为托管本机互操作有成本,我会告诉您编写一个C++/CLI函数,该函数包含20个参数,调用各种本机函数,然后调用go或execute。这为您提供了一个更简洁的界面,而不是闲
在前两者之间,问题在于还有谁可以使用这个库。如果C#代码是唯一使用它的代码,那么做你喜欢的。但例如,您可能有15或20个本机方法来设置各种属性,然后是执行实际工作的
go
或execute
方法。因为托管本机互操作有成本,我会告诉您编写一个C++/CLI函数,该函数包含20个参数,调用各种本机函数,然后调用go
或execute
。这为您提供了一个更简洁的界面,而不是闲聊,并降低了互操作成本。您可以使用pinvoke从任何.NET语言调用本机C/C++库。这里是一个快速教程。您还可以在C++中创建COM DLL,以便使用COM互操作直接从C内引用。除非您需要COM的优势,否则pinvoke是一条更容易的途径
当然,正如Konrad所言,使用托管C++解决方案包装C++ DLL。 例如,查看有关如何从C#调用win32 api的示例
从上面的MSDN链接(根据下面的注释进行修改):你可以调用本地C库,C++库假装是C库。你不能把#包括在内然后从C#那里得到破解。我从来没有说过你可以。最初的问题是如何与本机库进行互操作。我提出的解决方案是完全有效的。您的P/Invoke签名不正确--
put
和\u flushall
是使用\uu cdecl
调用约定导出的,但是DllImport
属性使用\uu stdcall
,除非您另有指定。(我知道这个错误是从你链接到的MSDN页面复制的,但你最好在这里修复它。)@ildjarn:谢谢你提供的信息。我四处查看,有趣的是,任何地方都没有任何示例显示使用这两种方法指定的调用约定(至少我看到过)。我使用两种调用约定测试了示例代码,两种约定都有效。我将修改答案,使其具有适当的约定。这会影响性能吗?在某些平台上,CLR会抛出一个关于堆栈不平衡的异常,在其他平台上,它能够自动纠正不平衡。我怀疑更正不是免费的。。。关于显示调用约定,这里要说明的是它没有显示的事实——C/C++的默认值是\uuu cdecl
,而.NET P/Invoke的默认值是\uu stdcall
,如果在任何一方都没有指定,那么默认值必须起作用。
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest
{
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int puts(
[MarshalAs(UnmanagedType.LPStr)]
string m);
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int _flushall();
public static void Main()
{
puts("Hello World!");
_flushall();
}
}