没有可以捕获托管变量的 lambda 的解决方法

2023-11-23

在 C++/CLI 中,您无法创建托管 lambda(就像在 C# 中一样),因此无法捕获托管变量。您可以创建常规方法(而不是 lambda),但您仍然无法捕获托管变量。

C++/CLI 代码中是否有可采用的标准解决方法?换句话说,我正在寻找一个可以在 C++/CLI 中使用的标准模式,以便从 C# 执行以下操作:

class A { }

class B
{
    void Foo()
    {
        A a = new A();
        Func<A> aFunc = () => a; // Captures a
    }
}

I could

  • 为我想要捕获的每个变量创建一个成员变量,然后在委托中使用该成员变量。这在一般情况下不起作用,因为您可能会两次调用想要处理不同捕获的 a 的方法,但它适用于常见情况。
  • 创建一个在其构造函数中执行捕获的嵌套类,然后使用该嵌套类的方法作为委托。这应该适用于一般情况,但这意味着每次我想捕获不同的变量时都需要一个嵌套类。

问题:是否有比上面更好的选择,或者上面的哪个选项是您的首选方法?

相关问题:

  • Visual C++ 2010 中作为 CLR (.NET) 委托/事件处理程序的 Lambda 表达式
  • C++/CLI 中的 Lambda 表达式

我为此目的编写了 Lamda2Delegate 结构。 实际上,它将 c++11 lambda 转换为任何 .net 委托。

使用示例:

    Thread^ TestLambaWrapper()
    {
        gcroot<String ^> str = "Testext";
        int i = 12345;
        Thread^ newThread = gcnew Thread(
            Lambda2Delegate<ParameterizedThreadStart>() = [&, str](Object ^ str2)
            {
                Sleep(2000);
                Console::WriteLine("Thread output = {0} {1} {2}", str, i, str2);
            }
        );
        newThread->Start("Nahnah");
        return newThread;
    }

对于你的情况:

    gcroot<A^> a = gcnew A();

    Func<A^> ^ aFunc = Lambda2Delegate<>() = [a](){ return (A^)a; };

    auto a2 = aFunc();

要捕获托管类,您需要用 gcroot 包装它们,并按值显式捕获。

以及 Lambda2Delegate.h 本身

    #pragma once
    #ifdef _MANAGED

    struct AutoDetectDelegateType {};

    template<typename TDelegate, typename TLambda, typename TRet, typename ...TParams>
    ref class LambdaHolder;

    template<typename TDelegate, typename TLambda, typename TRet, typename ...TParams>
    ref class LambdaHolder
    {
    public:
        inline LambdaHolder(const TLambda % func) { m_func = new TLambda(func); }
        !LambdaHolder() { delete m_func; }
        ~LambdaHolder() { !LambdaHolder(); }
    public:
        TRet Callback(TParams... params) { return (*m_func)(params...); }
        operator TDelegate ^ () { return gcnew TDelegate(this, &LambdaHolder::Callback); }
    private:
        TLambda * m_func;
    };

    template<typename TLambda, typename TRet, typename ...TParams>
    ref class LambdaHolder<AutoDetectDelegateType, TLambda, TRet, TParams...>
    {
    public:
        inline LambdaHolder(const TLambda % func) { m_func = new TLambda(func); }
        !LambdaHolder() { delete m_func; }
        ~LambdaHolder() { !LambdaHolder(); }
    public:
        TRet Callback(TParams... params) { return (*m_func)(params...); }
        template<typename TDelegate>
        operator TDelegate ^ () { return gcnew TDelegate(this, &LambdaHolder::Callback); }
    private:
        TLambda * m_func;
    };

    template <typename TDelegate, typename TLambda>
    struct get_labmda_holder : public get_labmda_holder < TDelegate, decltype(&TLambda::operator()) > {};

    template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
    struct get_labmda_holder < TDelegate, TRet(__clrcall TLambda::*)(TParams...) const >
    {
        typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
    };

    template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
    struct get_labmda_holder < TDelegate, TRet(__clrcall TLambda::*)(TParams...) >
    {
        typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
    };

    template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
    struct get_labmda_holder < TDelegate, TRet(__thiscall TLambda::*)(TParams...) const >
    {
        typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
    };

    template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
    struct get_labmda_holder < TDelegate, TRet(__thiscall TLambda::*)(TParams...)>
    {
        typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
    };

    template<typename TDelegate = AutoDetectDelegateType>
    struct Lambda2Delegate
    {
        template<typename TLambda>
        typename get_labmda_holder<TDelegate, TLambda>::TLambdaHolder ^ operator = (const TLambda % func)
        {
            return gcnew get_labmda_holder<TDelegate, TLambda>::TLambdaHolder(func);
        }
    };

    #endif

更新:不可能在托管成员函数中声明 C++ lambda 函数,但有解决方法 - 使用静态成员函数:

    ref class S
    {
    public:     
        int F(System::String ^ str)
        {
            return F(this, str);
        }
    private:
        //static function declaring c++ lambda
        static int F(S ^ pThis, System::String ^ str)
        {
            gcroot<System::String ^> localStr = "local string";
            System::Func<System::String ^, int> ^ func = Lambda2Delegate<>() = [=](System::String ^ str)
            {
                System::Console::WriteLine(str);
                System::Console::WriteLine(localStr);
                return str->Length;
            };
            return func(str);
        }
    };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

没有可以捕获托管变量的 lambda 的解决方法 的相关文章

  • 如何在 C++/CLI 中包装 C 库回调

    给定以下具有要求设置缓冲区的回调事件的 C 库 如何以类型安全的方式编写正确的 C CLI 包装器 The callback signature typedef void cdecl BUFFERALLOCATOR void opaque
  • cli/C++ 如何使用非托管类型元素定义 cli::array?

    我有一个本机 C C 结构 typedef struct AStruct 在 C CLI 代码中 我定义了一个委托和一个 cli 数组 如下所示 public delegate void UpdateDataDelegate AStruct
  • 如何正确声明 Font 变量? [复制]

    这个问题在这里已经有答案了 我有一个简单的问题 谁能告诉我这行有什么问题 Font printFont gcnew System Drawing Font Arial 10 我的编译器说 标识符 printFont 无法识别 我还包含命名空
  • 在 C++ 中将矩阵定义为数组数组并计算其逆矩阵

    不幸的是 我在 C 方面没有太多经验 并且我正在努力在 C 方面取得进步 首先 我定义了数组数组 以便形成一个 3x3 矩阵 array lt array lt double gt gt input gcnew array lt array
  • WSAEWOULDBLOCK 处理

    我已经在使用winsock 的C CLI 中为服务器编写了一个套接字 套接字使用异步方法来发送 接收和接受连接 在生产环境中实现套接字后 发送函数停止工作 并给出错误 WSAEWOULDBLOCK 根据我在网上的研究 这意味着套接字 IO
  • C 库的 C++/CLI 类包装器 - 回调

    我正在使用 C CLI 包装 C 库 C 库设计为从非托管 C 类中使用 这意味着库函数接受 C 对象指针 然后在回调中提供该指针 这使得回调代码能够将请求重定向到调用 C 对象中的适当事件函数 实际功能相当复杂 因此我将问题空间简化为几个
  • 嵌入式非托管 DLL 无法在 ASP.NET 中加载

    我正在为 WCF 服务开发 ASP NET 主机 该服务引用 C CLI 包装器库 该库本身引用非托管 DLL 基于这个问题 https stackoverflow com questions 2907169 asp net load un
  • 为什么我的 UDP 广播失败?

    我正在尝试发送 UDP 广播 但wireshark 没有报告任何流量 这是执行发送的代码片段 void SendBroadcast String ip 255 255 255 255 int port 30718 String messag
  • 在 C++ 声明中使用 ^ 字符意味着什么? [复制]

    这个问题在这里已经有答案了 可能的重复 C CLI 中插入符号 是什么意思 https stackoverflow com questions 202463 what does the caret mean in c cli 在 C CLR
  • C++/CLI 事件有监听器吗?

    在 C 中 我可以检查事件是否有任何侦听器 C 示例 public static event EventHandler OnClick if OnClick null OnClick null new EventArgs 在 C CLI 中
  • 当目标位于另一个 AppDomain 中时,非托管到托管的回调要慢得多

    我使用委托从非托管代码调用托管代码 当我调用默认 AppDomain 中的托管代码时 我测量到每次调用的平均时间为 5 4 纳秒 当我调用第二个 AppDomain 时 我测量到每次调用需要 194 纳秒 默认VS2017 x86发布配置
  • Silverlight 和 C++ 或 C++ 到 C# 正在进行代码转换吗?

    我正在开发一款基于绘图的产品 我希望按照优先级顺序为 iPhone 桌面 OS X Windows 平板电脑 基于 Silveright 的浏览器 Windows Mobile 和 Windows 生成版本 对于 GUI 可移植性 经典的答
  • 将 CLR 类型转换为 void* 并返回

    例如 如何正确转换 CLR 类型Foo to void 过一段时间再回来 场景是 我在 DLL 中有一些非托管代码 可以总结为 class Handler void obj void call void obj int detail voi
  • C++ CLI DLL 不会被 IIS7 加载,但仅当使用比 VS2008 新的版本构建时才加载

    对于我的开发环境 我使用 Windows 7 Ultimate x64 VS2008 V2010 和 VS2013 我的应用程序是用 C 编写的 远程测试服务器具有 Windows Web Server 2008 R2 x64 和 IIS
  • 如何在 C++/CLI 中转发声明委托?

    How 以下内容无效 delegate MyDelegate ref class MyDelegate delegate void MyDelegate 申报工作如下 public delegate void MyDelegate Obje
  • VC++ 代码 DOM 可以从 VS 插件访问吗?

    Visual Studio IntelliSense for VC 包括 完整 EDG C 解析器 http www edg com location c frontend 英特尔和其他公司也使用 由于插件可以访问 C Code DOM 如
  • 进程间并发文件写入

    我需要将不同进程的日志数据写入单个文件 我正在使用 Windows Mutex 它需要公共语言运行时支持 Mutex m gcnew Mutex false MyMutex m gt WaitOne File Open and Write
  • c++/cli 中的 gcroot

    gcroot 是什么意思 我在我正在阅读的代码中找到了它 gcroot 是一个 C cli 模板类 可以轻松地在 C cli 类中保存托管类型 例如 您可以拥有以下内容 include
  • 使用 C++/CLI 包装非托管 C++ 类库 - 问题 2 - 集合

    Note 这篇文章代表了我的询问的问题 2 两个问题中都会重复介绍部分 达到数字之前的所有文本 因为它是回答问题可能需要的背景信息 问题简介 我有一个非托管 C 库 其中包含多个 更高级别 库所共有和共享的类和函数 我现在需要向 C Net
  • 使用命名空间

    有什么区别 using System and using namespace System 是同一件事吗 thanks 是的 有区别 第一个无法编译 也许你的意思是这样的 using

随机推荐

  • 函数侦听器无法启动。 Azure函数应用程序时间触发

    当我在本地环境中从 Visual Studio 运行 azure 函数时 出现以下错误 函数 Function1 的侦听器无法启动 Microsoft WindowsAzure Storage 错误请求 这是我的代码 using Syste
  • Vim - 如何使您自己的映射可重复?

    我的 vimrc 中有以下映射 nmap
  • 将自定义上下文菜单项添加到 Windows 窗体标题栏

    I found a threadMSDN 上展示了如何将项目添加到 Windows 窗体标题栏的上下文菜单 不幸的是 它没有显示如何使用自定义菜单项注册事件 我一直无法弄清楚如何做到这一点 下面是一个示例应用程序 可以将其复制并粘贴到新的
  • django - 如何交叉检查 ModelAdmin 及其内联?

    我有两个模型 ModelParent 和 ModelChild 在主题模型上具有相同的 m2m 字段 ModelChild 在 ModelParent 上有一个外键 并且 ModelChild 在管理页面上被定义为 ModelParent
  • 发布请求 Axios:网络错误

    我使用 NodeJS 作为后端 使用 ReactJS 作为前端 我请求 Axios 网络时遇到问题 我所有的 Get 请求都有效 但是Post请求不起作用 我只是遇到这个错误 网络错误 我创建了一个简单的网络服务来向您展示我的问题 Serv
  • jquery .click 函数的基本延迟

    我有最基本的 jquery 函数 但我无法在文档中找到一种方法来在 1500 毫秒后触发此单击函数的内容 masonryRecall click function mainContent masonry 附 刚刚注意到 delay 函数 j
  • python 中的站点包是什么?如果您不是 root,您可以安装/使用它们吗?

    我正在尝试安装lldb在 Linux 中到我系统上的主目录 我没有 root 访问权限 并且我在尝试创建子目录的步骤中遇到了问题 usr lib python2 6 site packages 我在 Makefile 中找到了设置此变量的行
  • 创建一个粘在 UITableView 底部的 UIView

    我有一个grouped UITableView我想在我的最底部添加一个 UIButtonUITableView 我正在使用 Storyboard 和 UITableViewController 我不太确定需要在哪里添加代码或拖 放 UI 元
  • 如何使用 json.net 设置 json 路径的值

    我正在尝试在 JSON 结构中设置任意路径 但我很难弄清楚如何执行简单的设置值 我想要的是像 SetValue path value 这样的方法 其操作类似于 SelectToken 但如果路径不存在则创建路径并设置值 public voi
  • Perl - 从输入字符串中获取第一个“单词”

    我正在尝试编写一个 Perl 程序 该程序从文本文件中读取行 并且对于每一行 从该行中提取第一个 单词 并根据返回的字符串执行不同的操作 主循环如下所示 while
  • 如何从特定版本的 Google Sheet 读取数据?

    我在互联网上找到了从最新版本的Google Sheet读取数据的代码示例 如下所示 SpreadsheetService service new SpreadsheetService Print Google Spreadsheet Dem
  • 将“new-row”的 DataGridViewImageColumn 中的“red-cross”替换为自定义图像

    如果您指定AllowUserToAddRows在winforms中DataGridView用户可以在网格中手动添加新行 现在我想在一列中添加一个图像按钮 该按钮也应该显示在新行中 但我无法让它显示图像 只显示红十字图像 就像没有找到一样 这
  • Spring自定义注解多字段验证

    这里有一个有点贪心的问题 希望这个问题也能帮助其他想了解更多注释验证的人 我目前正在学习Spring 目前 我计划尝试一下自定义注释验证 我查了很多 现在知道主要有两种验证 一种是用于控制器的 另一种是使用 Valid的注解方法 这是我的场
  • PHP 在所有请求中保留变量

    在某些语言 C 或 NET 中 这将是静态变量 但在 PHP 中 每次请求后都会清除内存 我希望该值在所有请求中持续存在 我不想 SESSION 因为每个用户的情况都不同 为了帮助解释这里有一个例子 我想要一个像这样的可以计数的脚本 无论哪
  • 在 File.Create 之后关闭文件[重复]

    这个问题在这里已经有答案了 我检查文件是否存在 if File Exists myPath File Create myPath 但是 当我去创建一个StreamReader使用这个新创建的文件 我收到一条错误消息 该进程无法访问文件 此处
  • 摆脱停用词和标点符号

    我正在与 NLTK 停用词作斗争 这是我的代码 有人可以告诉我出了什么问题吗 from nltk corpus import stopwords def removeStopwords palabras return word for wo
  • 为什么在 HTC Desire 上发送短信时出现 NullPointerException,或者什么是 SubmitPdu?

    所以我得到这个堆栈跟踪 java lang NullPointerException at android telephony SmsMessage SubmitPdu
  • Akka:如何查找集群中的当前节点?

    从 Akka actor 内部 如何找到集群的节点 即本节点认为当前可以访问的节点 谢谢 丹尼尔 您实际上不需要订阅ClusterDomainEvent or MemberEvent 您只需访问state集群扩展的成员 例如 val clu
  • 相同美学的多个传说

    我正在尝试使用facet grid or facet wrap和这个结合geom raster 然而 在每个面板中 z审美是不同尺度的 例如 Data at end of question ggplot dd aes x y geom ra
  • 没有可以捕获托管变量的 lambda 的解决方法

    在 C CLI 中 您无法创建托管 lambda 就像在 C 中一样 因此无法捕获托管变量 您可以创建常规方法 而不是 lambda 但您仍然无法捕获托管变量 C CLI 代码中是否有可采用的标准解决方法 换句话说 我正在寻找一个可以在 C