我想建立一个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))')
很显然,我理解为什么它不起作用,但是我感觉应该可以解决它,而我只是没有足够的经验来解决它。
答案 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::function
和LogFunction
的传值效率可能更高无论如何,总是会构造对象(即,它们在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粗体。