从 C++ 回调到 C#

2023-12-12

假设我有一个用于计算 PI 的 C++ 库函数:

// pi.h:
#ifdef BUILDING_DLL
#define DLL_MACRO __declspec(dllexport)
#else
#define DLL_MACRO __declspec(dllimport)
#endif

namespace Cpp {
  class PI {
  public:
    static double DLL_MACRO compute();
  };
}; 

// pi.cpp: 
#include "pi.h"
#include <cmath>

double 
Cpp::PI::compute() {
   // Leibnitz summation formulae:
   double sum = 0.0;
   for(long n = 0; n < 100*1000*1000; n++)
     sum += 4.0*pow(-1.0, n)/(2*n + 1.0);
   return sum;
} 

我需要从 C# 调用这个函数,并且我想使用 C++/CLI 作为“桥梁”。然而这个 C++ 函数有点慢。因此,调用此函数的 C# 代码需要获取回调,以 % 形式告诉它该函数已经进行了多远。 C# 代码可能需要一些状态,例如进度条,处理此信息。 因此,来自 C++ 的回调必须进入 C# 端的成员函数。

所以我介绍一下:

// piCLI.h: The C++/CLI "bridge" between C# and C++
#include "pi.h"
#pragma once
namespace CLI {
   public ref class PI abstract {
   public:
      double compute() {
        return Cpp::PI::compute();
      }
      virtual void progress(int percentCompleted) = 0;        
   };
 }; 

and

 namespace CSharp
 {
    public class PI : CLI.PI
    {
       public override void progress(int percentCompleted)
       {
          System.Console.WriteLine(percentCompleted + "% completed.");
       }
     }
  }

现在调用 CSharp.PI.compute() 可以正常工作:-)。它按预期将调用转发给 Cpp::PI::compute()。

但是,当 Cpp::PI::compute() 运行时,如何让 C++ 库将进度更新转发到 CSharp.PI.progress() 呢?

预先感谢您的任何答复!


我也会采用函数指针/委托方法:

// pi.h:
#pragma once

#ifndef DLL_MACRO
#ifdef BUILDING_DLL
#define DLL_MACRO __declspec(dllexport)
#else
#define DLL_MACRO __declspec(dllimport)
#endif
#endif

namespace Cpp {
    typedef void (__stdcall *ComputeProgressCallback)(int);

    class PI {
    public:
        static double DLL_MACRO compute(ComputeProgressCallback callback);
    };
}

// pi.cpp: 
#include "pi.h"
#include <cmath>

double Cpp::PI::compute(Cpp::ComputeProgressCallback callback) {
    double sum = 0.;
    for (long n = 0L; n != 100000000L; ++n) {
        sum += 4. * std::pow(-1., n) / (2L * n + 1.);
        callback(/*impl*/);
    }
    return sum;
}
// piCLI.h: The C++/CLI "bridge" between C# and C++
#pragma once
#include "pi.h"

namespace CLI {
    public delegate void ComputeProgressDelegate(int percentCompleted);

    public ref class PI abstract sealed {
    public:
        static double compute(ComputeProgressDelegate^ callback) {
            using System::IntPtr;
            using System::Runtime::InteropServices::Marshal;

            IntPtr cbPtr = Marshal::GetFunctionPointerForDelegate(callback);
            return Cpp::PI::compute(
                static_cast<Cpp::ComputeProgressCallback>(cbPtr.ToPointer())
            );
        }
    };
}
namespace CSharp {
    public static class PI {
        public static double compute() {
            CLI.PI.compute(
                percentCompleted => System.Console.WriteLine(
                    percentCompleted.ToString() + "% completed."
                )
            );
        }
    }
}

或者,覆盖摘要progress方法而不是在 C# 端创建委托:

// piCLI.h: The C++/CLI "bridge" between C# and C++
#pragma once
#include "pi.h"

namespace CLI {
    public ref class PI abstract {
        delegate void ComputeProgressDelegate(int percentCompleted);

    public:
        double compute() {
            using System::IntPtr;
            using System::Runtime::InteropServices::Marshal;

            ComputeProgressDelegate^ callback = gcnew ComputeProgressDelegate(
                this,
                &PI::progress
            );
            IntPtr cbPtr = Marshal::GetFunctionPointerForDelegate(callback);
            return Cpp::PI::compute(
                static_cast<Cpp::ComputeProgressCallback>(cbPtr.ToPointer())
            );
        }

    protected:
        virtual void progress(int percentCompleted) abstract;
    };
}
namespace CSharp {
    public sealed class PI : CLI.PI {
        protected override void progress(int percentCompleted) {
            System.Console.WriteLine(
                percentCompleted.ToString() + "% completed."
            );
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 C++ 回调到 C# 的相关文章

  • 静态只读字符串数组

    我在我的 Web 应用程序中使用静态只读字符串数组 基本上数组有错误代码 我将所有类似的错误代码保存在一个数组中并检查该数组 而不是检查不同常量字符串中的每个错误代码 like public static readonly string m
  • 当我在组合框中选择一个项目时,如何防止 TextChanged 事件?

    我有一个TextChanged http msdn microsoft com en us library system windows forms control textchanged aspx我的事件ComboBox http msd
  • 以编程方式读取 SQL Server 查询计划建议的 SQL 特定执行的索引?

    如果我在 SSMS 中运行此命令 set showplan xml on GO exec some procedure arg1 arg2 arg3 GO set showplan xml off GO 我获得查询执行中涉及的完整调用堆栈的
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 这个可变参数模板示例有什么问题?

    基类是 include
  • 堆栈是向上增长还是向下增长?

    我在 C 中有这段代码 int q 10 int s 5 int a 3 printf Address of a d n int a printf Address of a 1 d n int a 1 printf Address of a
  • 如何减少具有多个单元的 PdfPTable 的内存消耗

    我正在使用 ITextSharp 创建一个 PDF 它由单个 PdfTable 组成 不幸的是 对于特定的数据集 由于创建了大量 PdfPCell 我遇到了内存不足异常 我已经分析了内存使用情况 我有近百万个单元格的 1 2 在这种情况下有
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke

随机推荐

  • Android:在AlertDialog内的多选ListView中选择项目

    我是 Android 开发新手 正在努力解决如何在由警报对话框托管的列表视图中选择某些项目的问题 在下面的代码中 lv setItemChecked 不起作用 因为尚未生成 listview 所以我想知道是否有任何 ListView 或 A
  • ExtJS4 中网格面板的颜色图例

    我有一个要求 网格中的每个单元格都可以根据某些标准从可用的 8 种颜色中选取任何颜色 之后 我需要在网格面板下方显示这 8 种颜色的颜色图例及其标签名称 有人可以建议我 ExtJS4 是否有任何类似的网格功能或者关于如何解决这个问题的任何想
  • Oauth google 趋势下载 CSV 文件 [重复]

    这个问题在这里已经有答案了 我正在尝试构建一个使用谷歌趋势和 或谷歌洞察数据的网络应用程序 但我遇到了一些障碍 仅当您登录有效的 Google 帐户时 Google 趋势才允许您下载 csv 文件 因此 我无法让我的网络应用程序下载并解析它
  • 为表中的动态文本框设置类验证

    我有一个表 其中有一行动态文本框 下面的例子 我通过单击 添加新目标来添加表中的行 下面的屏幕将出现 我想将验证类添加到表内的所有文本框 因此 当用户单击保存按钮时 它将选中所有文本框 我尝试使用这个 jquery 来实现 tbTarget
  • 识别字符串数组中的文本

    我现在正在为学校做一个项目 一个迷你文本编辑器 显然 基本功能之一是让用户插入文本 重点是我们要控制输入 使用循环 字符串和数组 do System out println Insira o seu texto duplo ENTER vo
  • tweepy 获取两个日期之间的推文

    我的 Python 代码如下 import tweepy consumer key consumer secret access token access token secret auth tweepy OAuthHandler cons
  • 当 div 的内容发生更改时,如何自动调整 div 的大小以适应其内容的大小?

    目前 我有这个 DIV 其中有一个注册表单位于页面中央 DIV 的内容来自 ascx 页面 这做得很好 现在 如果用户尝试填写不唯一的名称 某些 jQuery 会在用户名字段旁边添加一条错误消息 这破坏了 DIV 的布局 因为现在的内容比以
  • C# 字符串替换实际上并不替换字符串中的值[重复]

    这个问题在这里已经有答案了 我正在尝试用另一个字符串替换字符串的一部分 更准确地说 我有C Users Desktop Project bin Debug 我正在尝试更换 bin Debug with Resources People 我已
  • 在 Xcode 4 中移动本地化文件夹

    我最近从 Xcode 3 升级到 Xcode 4 2 并迁移了现有的 iOS 应用程序以使用这个新版本 该应用程序已本地化 我现在想添加另一种语言 在 Xcode 4 下 当我添加新的本地化版本时 它会在项目根目录中创建特定于国家 地区的文
  • WCF 序列化与对象继承?

    我有两个对象 一个是我们企业层面的 一个是我们服务层面的 服务对象继承自企业 这是一个简单的例子 DataContract public class EnterpriseObject DataMember int ID get set st
  • Powershell 对象未通过管道传输到函数

    我有两个函数 一个函数创建一个自定义对象 完成后将通过管道传输到下一个函数 问题是第二个函数没有正确接收我的对象 我没有使用管道 而是尝试设置一个变量 然后将该变量通过管道传递给函数 下面是两个函数 其输出为返回对象上的 get membe
  • 如何从命令行以管理员身份运行应用程序 (TestComplete)

    设想 我正在编写一个 powershell 脚本来自动化一些 UI 测试 我必须做很多事情 从存储库中检查代码 构建 复制安装程序 然后最后我想运行 TestComplete 并测试安装程序用户界面 安装程序在写入程序文件 注册表等时以提升
  • “gps”位置提供程序需要 Android 6.0 的 ACCESS_FINE_LOCATION 权限

    在 android 清单文件中 我添加了以下 GPS 访问位置的权限
  • Bison - 如何打印解析树

    你好 我正在研究一头小野牛 以了解它是如何工作的 野牛应该解析一个句子 句子是由表达式组成的 表达式是由单词组成的 以下是我的代码 include
  • Android和数据存储空间?

    我想知道我的 Android 应用程序有多少数据存储可用 我需要缓存大量文件 并且我正在考虑将其存储在共享首选项中 这样如果卸载应用程序 它就会被删除 毕竟它只是很多缓存文件 我想我也可以使用 SDCard 但是我无法控制用户在应用程序之外
  • 在 Rust 中更改树中的节点

    我正在尝试编写一个函数 在给定树结构的情况下 返回该树的副本 但节点在特定索引处发生更改 这是我到目前为止所拥有的 derive Clone pub enum Node Value u32 Branch u32 Box
  • 如何在没有 localStream 的情况下创建对等连接?

    我只想实现一个客户端发送 mediaSteam and a另一个收到了媒体Steam 所以接收者客户端不需要添加 localSteam 我只编写 pc addStream null 但不起作用 我如何通过 WebRtc 实现这一目标 不要打
  • key-id 位于签名中的密钥未签署此提交

    我正在尝试签署我的 git 提交 但是当我将它们推送到 GitHub 时 他们有Unverified徽章和 key id 位于签名中的密钥未签署此提交 有人可能想欺骗你 GPG 密钥 ID mykeyid 我发现这很神秘 在我的世界中 签名
  • 为什么 GWT 2.7 停止使用 GWT Designer?

    As per GWT 2 7 0 RC1 发行说明 GWT Designer 已弃用 我在项目中使用该工具进行一些复杂的 UI 设计 只是不知道为什么会发生这种情况以及没有它的替代方案是什么 GWT Designer 不再是 GWT 指导委
  • 从 C++ 回调到 C#

    假设我有一个用于计算 PI 的 C 库函数 pi h ifdef BUILDING DLL define DLL MACRO declspec dllexport else define DLL MACRO declspec dllimpo