如何使用 C++ lambda 将成员函数指针转换为普通函数指针以用作回调

Posted

技术标签:

【中文标题】如何使用 C++ lambda 将成员函数指针转换为普通函数指针以用作回调【英文标题】:How to use a C++ lambda to convert a member function pointer to a normal function pointer for use as a callback 【发布时间】:2019-05-10 09:23:32 【问题描述】:

我有一些需要 C 函数的代码,但我想实例化一堆类实例并将该类的成员函数作为 C 函数传递。我需要同时捕获 N 个实例。我希望我可以作为 lambda 来做到这一点。

生成的函数应该是这样的(大致):

// This is the code I want to interface with:

typedef void func(ParamClass param); // ParamClass is NOT my class

extern void notMyCode1(func funcArg); // Code I want to call, saves funcArg
extern void notMyCode2()  // uses saved funcArgs


// Here is the type of class I want to instantiate:

class MyClass 
   public:
       MyClass(int arg) : saveArg(arg) 

       int saveArg;

   void myFunc(ParamClass param) 
       // uses saveArg and param to do the right action
   

;

void useCase(void) 
   for (int i = 0; i < max; ++i) 
       MyClass myInstance(Myclass(i)); // maybe need vector to hold these?
       notMyCode1(myInstance.myFunc); // this code is what I don't know how to write
    
    notMyCode2();

背景。我要调用的库是 Google Benchmark。 notMyCode1 是他们的基准注册函数。 notMyCode2 运行已注册的基准。 ParamClass 是他们的代码传递给基准的数据。

现在,通常情况下,将一个简单的 C 函数传递给注册代码,一个用于希望运行的每个基准测试。但是,我想通过这个数字“i”一遍又一遍地运行相同的代码,并将每个“i”视为一个单独的基准。所以,我想在一个类中捕获“i”(或通过一个 lambda,但是会产生多个 C 函数指针,每个指针中都绑定了“i”的值)。我尝试将“i”作为基准的参数并将其传入,但是基准代码将“i”视为要总结的东西(并且我希望每个“i”都被视为具有不同统计参数的唯一基准待计算)。

这看起来应该很简单,(它只是一个闭包),但我对函数指针(或 C++ lambdas)并不熟悉。如果是我的代码,我只会传入类实例,但不是。

我见过在类中使用静态函数的示例,但我特别想捕获“i”的值并获取多个函数指针,每个函数指针都捕获不同的“i”值。

【问题讨论】:

看看documentation,你完全不局限于C函数。你可以设置一个range和pass arbitrary arguments比如你的班级就好了。 @nwp 成员函数指针仍然与常规函数指针不是同一类型的野兽(并且它们不能相互转换)。如果它们处理得很好,那么这是最好的解决方案,但是BENCHMARK_CAPTURE 宏/函数是否正确处理它们? 他们不需要处理它。你自己做。您编写了一个基准函数,该函数将类作为额外参数并仅调用成员函数。或者它需要一个指向类的指针和一个指向成员函数的指针并使用std::invoke。由于该函数始终将benchmark::State&amp; state 作为第一个参数,因此不必编写基准函数的机会很小。 对。星期五是真实的。我的思维没有达到 100% 来自进一步调查。看起来如果被调用者想要一个 C 函数,这是不可能的。但是,我发现调用者将结果包装在一个类中,所以我定义了自己的类并替换了它。看起来他们也有一个接受 lambdas 而不仅仅是 C 函数的版本。 【参考方案1】:

你不能。

如果 lambda 是无状态的(即没有捕获),它只会转换为函数指针。要从 lambda 调用成员函数,您需要一个指向用于调用成员函数的对象的指针。这被捕获,使 lambda 对象无法转换为简单的函数指针。

您可能拥有的唯一选择是在编译时使用模板进行索引参数化。然后您返回使用可以作为 C 回调传递的类模板的简单静态函数。

【讨论】:

以上是关于如何使用 C++ lambda 将成员函数指针转换为普通函数指针以用作回调的主要内容,如果未能解决你的问题,请参考以下文章

C++ 在 lambda 函数中使用 this 指针和绑定

将 C++ 成员函数指针传递给 STL 算法

将指向成员的 C++ 指针转换为 C#

c++ 成员函数 普通函数指针转换

如何将函数指针传递给成员函数c++?

C++成员函数指针指向全局函数指针