c++内部c#性能的通讯
本文关键字:性能 内部 c++ | 更新日期: 2023-09-27 18:10:26
我有一个用c#编写的程序(我们称之为ValidationChecker)。这个ValidationChecker需要OMPL库,该库只能由python或c++使用。因此,生成了一个c++解决方案,并将其编译为。exe。
ValidationChecker启动exe并打开自己与.exe之间的TCP通信。之后,ValidationChecker通过tcp通信向exe发送一些开始数据,exe从开始数据中生成一些数据。在创建一个新数据包后的某些过程中,该数据由exe转换,然后发送到ValidationChecker以检查该新生成的数据是否有效。因此,exe将等待ValidationCecker发回确认该数据是否有效。这是一个循环,直到exe生成足够的有效数据包。
我现在的问题是:从创建新数据包到ValidationChecker发送确认的整个循环最多需要120ms。必须创建的数据包数量在100到3000之间变化。首先,我做了一些分析,注意到转换数据的过程需要60-70ms,所以我优化了这个过程,现在这个过程只需要1-2ms。(首先我做了一些嵌入python,现在我调用一个dll代替)我的想法是,这将加快我的循环。但整个循环仍然需要120毫秒,我想知道为什么?因此,我对持续时间的测量显示,数据的转换现在更快了,但将数据发送到c#的通信更慢了,几乎与减少的百分比完全相同。
我考虑过将c++解决方案直接集成到ValidationChecker中,但我不太确定这是否真的可能。我在pinvoke, com对象上读了一些东西,并从我的c++解决方案中生成了一个dll。但这真的会加快c#程序和c++计算之间的通信速度吗还是会比实际的tcp通信慢?另一个问题是,需要交换数据,而不仅仅是通过调用函数并返回一些值。有一个c#函数必须调用c#函数进行验证检查,并且需要一个返回值来确认该数据是否有效。
这么多的文字,我希望你理解我的想法,可以帮助我更快的解决方案。因为我不太确定是否可以在dll中调用c#函数。如果这个解决方案比以前使用tcp的解决方案快,
因为你没有添加任何代码,你有什么类型的函数,我将给你一个简单的例子,如何使用p/Invoke来调用c#中的非托管库。P/invoke比TCP连接快得多,P/invoke的唯一开销是必须完成的参数转换。
在示例中,您看到[return: MarshalAs(UnmanagedType.Bool)]
指示运行时将返回值转换为bool值。这是获得正确值所必需的。这也可以用于方法参数。
using System;
using System.Runtime.InteropServices;
class BeepSample
{
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool Beep(uint dwFreq, uint dwDuration);
static void Main()
{
Console.WriteLine("Testing PC speaker...");
var success = Beep(200, 5);
Console.WriteLine("Testing complete. " + success);
}
这样做的"内置"方法(无需从c#中p/Export)是从c++ DLL中导出一个"入口点"。问题是c#不能直接使用c++,所以你需要一个干净的C接口(你不能在方法签名中使用任何c++的东西)。
在c++中,你可以这样做:
extern "C"
{
struct PackageRequest
{
LPWSTR SomeString;
int32_t SomeInt;
};
struct PackageResult
{
LPWSTR SomeString;
int32_t SomeInt;
};
__declspec(dllexport) HRESULT DoSomething(PackageRequest& request, PackageResult& response)
{
//...
}
}
然后在c#中:
static class NativeMethods
{
public struct PackageRequest
{
[MarshalAs(UnmanagedType.LPWStr)]
public StringBuilder SomeString;
public int SomeInt;
}
public struct PackageReponse
{
[MarshalAs(UnmanagedType.LPWStr)]
public StringBuilder SomeString;
public int SomeInt;
}
[DllImport("MyDll.dll")]
private static extern int DoSomething(ref PackageRequest req, out PackageReponse resp);
public static PackageReponse DoSomething(PackageRequest req)
{
PackageReponse resp;
var rc = DoSomething(ref req, out resp);
if (rc != 0)
throw new Exception("...");
return resp;
}
}