【问题标题】:C++ inside of C# performance of communication [duplicate]C#内部的C++通信性能[重复]
【发布时间】:2015-08-31 09:18:54
【问题描述】:

我有一个用 c# 编码的程序(我们称之为 ValidationChecker)。此 ValidationChecker 需要 OMPL 库,该库只能由 python 或 c++ 使用。因此生成了一个 c++ 解决方案,该解决方案被编译为 .exe。

ValidationChecker 启动 exe 并打开它自己和 .exe 之间的 TCP 通信。之后,ValidationChecker 通过 tcp 通信向 exe 发送一些启动数据,并且 exe 从启动数据中生成一些数据。在创建一个新数据包后的某些过程中,此数据由 exe 转换,然后发送到 ValidationChecker 以检查此新生成的数据是否有效。因此,如果该数据有效或无效,exe 将等待 ValidationChecker 发回确认信息。这是一个循环,直到 exe 生成足够的有效数据包。

我现在的问题是: 从创建新数据包到 ValidationChecker 发送确认的整个循环最多需要 120 毫秒。必须创建的数据包的数量在 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# 调用 C++ dll,而不是使用 tcp 连接。
  • 那么有没有办法从 C++ dll 中调用 C# 函数?或者你将如何管理它? p/invoke 真的比 tcp 连接快吗?
  • 哦,我有点误解你的问题了。您尝试从 C++ 代码中调用 C# 代码。现在,这不是由 P/invoke 完成的。但也许这有帮助:support.microsoft.com/en-us/kb/828736(我认为这比 TCP 连接更快)
  • 不是我的错!问题是我有两个功能。一个 C# 和一个 C++。但我想将 C++ 集成到 C# 中。因此我读到我必须从我的 C++ 代码中生成一个 dll。但是在函数内部,我需要一些交换可能性来调用 C# 函数来检查数据。所以过程是 C# 调用 DLL 中的 C++ 函数,这个 C++ 函数调用 C# 函数进行验证并返回确认。
  • 那你将使用P/invoke。

标签: c# c++ communication


【解决方案1】:

由于你没有添加任何代码你有什么样的功能,我将给你一个简单的例子,说明如何使用 P/Invoke 来调用 C# 中的非托管库。 P/invoke 比 TCP 连接快得多,P/invoke 唯一的开销是必须完成的参数转换。

在示例中,您会看到[return: MarshalAs(UnmanagedType.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);
     }

【讨论】:

  • 如果 P/Invoke 恰好不足以满足您的需求,请查看 C++/CLI。
  • 好的,这也是我在其他一些示例中看到的,但现在对我来说最大的问号是如何在此示例中从“dll 内部”调用 c​​# 函数?或者这是不可能的?
  • 我不明白“dll 内部”是什么意思。您能否用代码或图像更新您的问题以更准确地解释。
【解决方案2】:

执行此操作的“内置”方法(无需从 C# 进行 P/Export)是从 C++ DLL 中导出“入口点”。问题是 C# 不能真正直接使用 C++,所以你需要一个 clean 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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 2012-09-13
    • 2011-02-04
    相关资源
    最近更新 更多