.net 将ref类成员函数作为参数传递

.net 将ref类成员函数作为参数传递,.net,c++-cli,.net,C++ Cli,我正在尝试创建一个包装器,允许在一行程序中创建System::Task对象。到目前为止,我有以下工作- ref class TaskRunner abstract sealed { public: generic<typename TArg0> static Task^ Create(Action<TArg0>^ f, TArg0 arg0) { return Task::Run((gcnew BindAction1<TArg0>

我正在尝试创建一个包装器,允许在一行程序中创建System::Task对象。到目前为止,我有以下工作-

ref class TaskRunner abstract sealed
{
public:
    generic<typename TArg0>
    static Task^ Create(Action<TArg0>^ f, TArg0 arg0) {
        return Task::Run((gcnew BindAction1<TArg0>(f, arg0))->binder);
    }
private:
    generic<typename TArg0>
    ref class BindAction1
    {
        initonly TArg0 _arg0;
        Action<TArg0>^ const f;
        void _() { return f(_arg0); }
    public:
        initonly Action^ binder;
        BindAction1(Action<TArg0>^ f, TArg0 arg0) : f(f), _arg0(arg0) {
            binder = gcnew Action(this, &BindAction1::_);
        }
    };
}
并在Create中调用gcnewaction(obj,func)。我不知道这是否可能。如果是,我将如何声明create的参数

实际上,它们需要与动作委托相同。查看system library操作似乎需要一个system::Object和system::IntPtr,但我无法将它们用作参数

*更新-感谢IllidanS4提供完整的答案以及您的帮助。对于任何试图在其答案中使用代码的人,Visual Studio 2015中似乎存在一个编译器错误,它要求为每个参数链长度覆盖委托类型。

来自ECMA-372:

一种程序,它试图在任何其他上下文中获取非本机类的成员函数的地址 而不是在创建委托时,是格式错误的。没有指向的成员的成员表示形式的指针 非本地类

不幸的是,这意味着
&Class::Function
无效。在我看来,这个限制是没有用的,因为CIL中的指令正是委托构造中非编译的指令。遗憾的是,C++/CLI中缺少“指向托管函数的指针”类型,尽管它显然存在于CIL中

所以不,必须在委托中传递方法。但是,如果您对宏持开放态度,则可以使用以下内容:

#define CreateTask(obj, func, arg) TaskRunner::Create(gcnew System::Action<decltype(arg)>(obj, func), arg)
#定义CreateTask(obj,func,arg)TaskRunner::Create(gcnew System::Action(obj,func,arg)
编辑:要使它也适用于Func案例有点棘手,但它也适用于一些模板:

template <class Ret, class... Args>
struct delegate_type
{
    using type = System::Func<Args..., Ret>;
};

template <class... Args>
struct delegate_type<void, Args...>
{
    using type = System::Action<Args...>;
};

#define CreateTask(obj, func, arg) TaskRunner::Create(gcnew delegate_type<decltype(obj->func(arg)), decltype(arg)>::type(obj, &func), arg)
模板
结构委托类型
{
使用type=System::Func;
};
模板
结构委托类型
{
使用type=System::Action;
};
#定义CreateTask(obj,func,arg)TaskRunner::Create(gcnew delegate_typefunc(arg)),decltype(arg)>::type(obj,&func),arg)

只是不要将它与
&Class::Function
一起使用,而是传递
Class::Function

谢谢!真遗憾。宏没有那么干净,但它们可以完成任务。这实际上是一组函数,用于各种数量的参数/Func以及操作。宏中是否有任何方法可以处理Func情况?(即,提取返回类型以输入Func类型说明符)@Hector Maybe。我只需要弄清楚如何获取托管函数的返回类型。我花了30分钟的时间自己尝试,但运气不好。如果你能解决这个问题,我将不胜感激——我内心的完美主义者对必须手动创建代理并不满意——尤其是我看不出这种限制的技术原因。@Hector花费的时间比我预期的要长,但我还是把它编译好了(尽管IntelliSense似乎不喜欢它)。我只是希望您也不希望它支持多个参数:-P理论上,
部分也可以省略,但我无法解决如何在
decltype
上调用静态函数。现在我印象深刻了!所以如果我想支持多个参数。。这可行吗?一旦我有了发电机的基本概念,我就可以很高兴地编写它了。我希望“…”表示委托类型能够接受多个参数,但“TaskRunner::Create(gcnew TaskRunner::delegate_typefunc(arg0,arg1))、decltype(arg0)、decltype(arg1)>::type(obj,&func)、arg0、arg1”会因“System::Action”而失败:泛型参数太多“将方法名自动转换为委托是C语言的一个特点。但不是C++/CLI,它避免了这样的语法。与C++不同。但是混合语言当然是.net的一项功能,没有明显的理由不能用C#编写这段代码,因为它不进行任何本机互操作。@HansPassant-这是一个围绕本机库的包装库,需要由C#或C++CLI调用。也就是说,返回的任务包括对本机的调用。除非有一种方法将C和C++混合到一个文件中,所以我知道做你建议的唯一方法是在C++ CLI一个周围的一个单独的C库,这不是非常理想的。请还包括有关代码的超载:TaskRuns::创建< /Cord>,以及你使用的代码> CurATETASK2。如果我指定了
“string”
而不是
gcnew string(“string”)
,我会遇到一些错误。奇怪的是,在Visual Studio中,即使在IntelliSense中直接创建普通委托时,我也会遇到类似的错误,但我会将其编译。也许你有一些旧版本的编译器,或者遇到了一些奇怪的错误。考虑到微软不费心更新C++/CLI,这并不奇怪。是的,VS 2017。他们可能已经修补了编译器。
#define CreateTask(obj, func, arg) TaskRunner::Create(gcnew System::Action<decltype(arg)>(obj, func), arg)
template <class Ret, class... Args>
struct delegate_type
{
    using type = System::Func<Args..., Ret>;
};

template <class... Args>
struct delegate_type<void, Args...>
{
    using type = System::Action<Args...>;
};

#define CreateTask(obj, func, arg) TaskRunner::Create(gcnew delegate_type<decltype(obj->func(arg)), decltype(arg)>::type(obj, &func), arg)