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的解决方案快,

c++内部c#性能的通讯

因为你没有添加任何代码,你有什么类型的函数,我将给你一个简单的例子,如何使用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;
    }
}