修改成员变量的C++回调

C++ callback that modifies member variable

我有一个 C++ class 提供到 OpenCL 的绑定。 OpenCL 函数通过指向类型 cl::make_kernel 的可调用对象的指针公开。要使用相应的对象,我必须在 class.

中创建此指针

由于 OpenCL 的设计,我无法创建 cl::make_kernel 对象,直到我通过函数初始化 OpenCL 引擎让我们称它为 openCLCompile,它为我提供 cl::Program 构建所需的对象 cl::make_kernel.

假设我想公开两个 OpenCL 函数,每个函数都在单独的文件中。函数 openCLCompile 接受所有文件的向量,并且只能调用一次。通常我的 class 如下所示:

    class OpenCLWrapper
    {
    public:
         initializeOpenCL()
         {
              std::vector<std::string> CLfiles;
              CLFiles.push_back("functionA.cl");
              CLFiles.push_back("functionB.cl");
              cl::Program program = openCLCompile(CLfiles);
              CLfunctionA = std::make_shared<cl::make_kernel<cl::Buffer&>>(cl::Kernel(program, "FUNCTION1"));
              CLfunctionB = std::make_shared<cl::make_kernel<cl::Buffer&,  cl_double16&>>(cl::Kernel(program, "FUNCTION2"));
         }
    private:
         std::shared_ptr<cl::make_kernel<cl::Buffer&>> CLfunctionA;
         std::shared_ptr<cl::make_kernel<cl::Buffer&, cl_double16&>> CLfunctionB;
    }

然而,通过使用此逻辑,我必须始终编译“functionA.cl”和“functionB.cl”文件并创建指针 CLfunctionA 和 CLfunctionB。

我想要专门的函数来注册 openCL 两个函数分开的函数。通过这种方式,可以保留第二个指针 nullptr。但是,当我在调用 initializeOpenCL 之前调用此寄存器函数时,我没有 cl::Program 对象来创建相应的 cl::make_kernel 对象。但是,最好指定如何通过将更改成员变量的代码来初始化寄存器函数范围内的相应对象。所以我决定用下面的逻辑来解决

    class OpenCLWrapper
    {
    public:
         registerFunctionA()
         {
               CLFiles.push_back("functionA.cl");
               std::function<void(cl::Program)> f = [this](cl::Program program) {
                    CLfunctionA = std::make_shared<cl::make_kernel<cl::Buffer&>>(cl::Kernel(program, "FUNCTION1"));
               };
               callbacks.push_back(f);
         }

         registerFunctionB()
         {
              CLFiles.push_back("functionB.cl");
              std::function<void(cl::Program)> f = [this](cl::Program program) 
              {
                   CLfunctionB = std::make_shared<cl::make_kernel<cl::Buffer&,  cl_double16&>>(cl::Kernel(program, "FUNCTION2"));
              };
              callbacks.push_back(f);
         }

         initializeOpenCL()
         {
               cl::Program p = openCLCompile(CLfiles);
               for(std::function<void(cl::Program)> f : callbacks)
               {
                    f(p);
               }
         }
    private:
         std::shared_ptr<cl::make_kernel<cl::Buffer&>> CLfunctionA;
         std::shared_ptr<cl::make_kernel<cl::Buffer&, cl_double16&>> CLfunctionB;
         std::vector<std::string> CLfiles;
         std::vector<std::function<void(cl::Program)>> callbacks;
    }

它似乎有效,但我想知道这是否可以实现,不会泄漏内存,或者我应该以其他方式实现这些回调。

总的来说我觉得不错,我不相信有任何内存泄漏。我会推荐这个主要用于节省您一些打字时间的小改动。

callbacks.push_back([this](cl::Program program){ ... });

而不是

std::function<void(cl::Program)> f = [this](cl::Program program) { ... };
callbacks.push_back(f);

旁注:

通常最好使用 std::vector::emplace_back(...) 而不是 std::vector::push_back(...),原因已列出 here

并且 auto 关键字可能对您有所帮助,因为它可以使

for(std::function<void(cl::Program)> f : callbacks)

进入

for(auto f : callbacks)

至少在我看来,它更容易阅读,更容易输入,并且不需要考虑您正在处理的类型的确切名称是什么