有没有一种方法可以将void(*)(uint32_t,void(*)(uint32_t))转换为std :: function <void(uint32_t,std :: function <void(uint32_t)>)>?

时间:2019-10-13 10:54:57

标签: c++ c++11

我想建立一个C ++库,该库也可以在C语言中使用。 这是我希望能够在C中编译的头文件:

typedef void (*log_function_t)(const char *);
typedef void (*delay_function_callback_t)(uint32_t);
typedef void (*delay_function_t)(uint32_t, delay_function_callback_t);

extern "C" void core_init(log_function_t logFunction, delay_function_t delayFunction);

但是,由于我是用C ++语言编写的库,因此最好使用std :: function对象而不是函数指针,因此我想这样调用函数:

using LogFunction = std::function<void(const char*)>;
using DelayFunctionCallback = std::function<void(uint32_t)>;
using DelayFunction = std::function<void(uint32_t, DelayFunctionCallback)>;

void setLogFunction(const LogFunction& logFunction);
void setDelayFunction(const DelayFunction& delayFunction);

调用setLogFunction很好,但是当我尝试调用setDelayFunction时不起作用。

void core_init(log_function_t logFunction, delay_function_t delayFunction)
{
    Utility::getInstance().setLogFunction(logFunction);
    Utility::getInstance().setDelayFunction(delayFunction);
}

它说:Reference to type 'const DelayFunction' (aka 'const function<void (unsigned int, function<void (unsigned int)>)>') could not bind to an lvalue of type 'delay_function_t' (aka 'void(*)(unsigned int, void (*)(unsigned int))')

很显然,我理解为什么它不起作用,但是我感觉应该可以解决它,而我只是没有足够的经验来解决它。

2 个答案:

答案 0 :(得分:2)

您要问的似乎是将函数指针从C传递到C ++,其中函数采用std::function作为参数。恐怕这是不可能的,因为C无法传递以std::vector作为参数的函数指针。

调用Utility::getInstance().setDelayFunction(delayFunction)时,将对专用std::function(即DelayFunction)的ctor进行匹配以从函数指针进行构造。但是,匹配失败,因为(DelayFunction的ctor接受专用的std::function(即DelayFunctionCallback)而不是函数指针(即delay_function_callback_t)作为其第二个参数。

我认为问题出在std::function的实现中,该实现封装了函数指针并擦除了后者的类型。 (请参阅How is std::function implemented?)结果是,C ++ std::function与普通C函数指针的类型不同。

要解决此问题,您可以稍微放松C ++风格,然后声明DelayFunction接受void(*)(unsigned)。也就是说,在C ++文件中:

using LogFunction = std::function<void(const char*)>;
using DelayFunction = std::function<void(unsigned, delay_function_callback_t)>;
//                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^

编辑:重新。从C ++调用DelayFunction对象的评论,而不是将lamba函数作为回调传递(由于上面的解决方法会失败,因为lambda函数只能构造DelayFunctionCallback,而不能构造{{ 1}}),将回调实现为静态成员函数并直接使用它可能会更容易:

delay_function_callback_t

顺便说一句,如果Utility::getInstance().delay(delay, (delay_function_callback_t)&Utility::next); 将在内部存储Utility对象,则由于std::functionLogFunction的传值效率可能更高无论如何,总是会构造对象(即,它们在DelayFunction中是右值)。

答案 1 :(得分:1)

void(*)()std::function<void()>根本不同。

您可以通过void(*)( void* ), void*来接近自己; std函数同时具有可调用性状态,函数指针仅具有可调用性。 (std函数还带有RTTI以及如何清除状态和如何复制状态)。

现在,您可以将void(*)()转换为更强大的std函数;但不是相反。调用发生时,函数的参数会以其他方式转换。

struct callback {
  void* state;
  void(*action)(int32_t);
  void(*cleanup)(void*);
  void*(*copy)(void*);
};

相当于std::function<void(int32_t)>的C粗体。