简体   繁体   English

有没有办法将 void (*)(uint32_t, void (*)(uint32_t)) 转换为 std::function <void(uint32_t, std::function<void(uint32_t)> )&gt;?</void(uint32_t,>

[英]Is there a way to convert void (*)(uint32_t, void (*)(uint32_t)) to std::function<void(uint32_t, std::function<void(uint32_t)>)>?

I'd like to build a C++ library which is usable from C as well.我想构建一个 C++ 库,它也可以从 C 中使用。 This is the header file I want to be able to compile in C:这是我希望能够在 C 中编译的 header 文件:

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);

However, since I'm writing the library in C++, it would be nice to work with std::function objects instead of function pointers, so I'd like to call functions like this:但是,由于我正在 C++ 中编写库,因此使用 std::function 对象而不是 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);

Calling the setLogFunction works just fine, but when I try to call setDelayFunction it doesn't work.调用setLogFunction工作得很好,但是当我尝试调用setDelayFunction时它不起作用。

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

It says: 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))')它说: 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))')

Obviously I understand why it doesn't work, but I have a feeling that it should be possible to solve and I'm just not experienced enough to solve it.显然我明白为什么它不起作用,但我有一种感觉应该可以解决,我只是没有足够的经验来解决它。

What you're asking seem to be passing a function pointer from C to C++ where the function takes a std::function as argument. What you're asking seem to be passing a function pointer from C to C++ where the function takes a std::function as argument. I'm afraid this is not possible just as C can't pass a function pointer that takes a std::vector as argument.恐怕这是不可能的,因为 C 无法传递以std::vector作为参数的 function 指针。

When calling Utility::getInstance().setDelayFunction(delayFunction) , the ctor of a specialized std::function (ie DelayFunction ) is matched to construct from a function pointer.当调用Utility::getInstance().setDelayFunction(delayFunction)时,专门的std::function (即DelayFunction )的 ctor 被匹配以从 function 指针构造。 However, the match fails because the ctor (of DelayFunction ) accepts as its 2nd argument a specialized std::function (ie DelayFunctionCallback ), rather than a function pointer (ie delay_function_callback_t ).但是,匹配失败,因为(延迟函数的)ctor 接受一个专门的std::function DelayFunctionCallback DelayFunction作为其第二个参数,而不是一个 function 指针(即delay_function_callback_t )。

I think the problem lies in the implementation of std::function , which encapsulates the function pointer and erases the latter's type.我认为问题在于std::function的实现,它封装了 function 指针并擦除了后者的类型。 (See How is std::function implemented? ) As a result, a C++ std::function is a different type than a plain-C function pointer. (See How is std::function implemented? ) As a result, a C++ std::function is a different type than a plain-C function pointer.

To workaround this, you could relax the C++-ishness a bit and declare DelayFunction as accepting void(*)(unsigned) instead.要解决此问题,您可以稍微放松 C++ 风格,并将DelayFunction声明为接受void(*)(unsigned) Ie, in the C++ file:即在C++文件中:

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

EDIT: Re.编辑:回复。 the comment on calling the DelayFunction object from C++, instead of passing a lamba function as the callback (which would fail with the workaround above, since the lambda function can only construct a DelayFunctionCallback , not a delay_function_callback_t ), it might be easier to implement the callback as a static member function and use it directly: the comment on calling the DelayFunction object from C++, instead of passing a lamba function as the callback (which would fail with the workaround above, since the lambda function can only construct a DelayFunctionCallback , not a delay_function_callback_t ), it might be easier to implement the回调为 static 成员 function 并直接使用它:

Utility::getInstance().delay(delay, (delay_function_callback_t)&Utility::next);

BTW, if Utility is going to store the std::function objects internally, then it may be more efficient to pass-by-value, since the LogFunction and DelayFunction objects will always be constructed anyway (ie they are rvalue in core_init ).顺便说一句,如果Utility打算在内部存储std::function对象,那么按值传递可能更有效,因为无论如何都会构造LogFunctionDelayFunction对象(即它们是core_init中的右值)。

A void(*)() is fundamentally different from a std::function<void()> . void(*)()std::function<void()>根本不同。

You can get closer with a void(*)( void* ), void* ;你可以用void(*)( void* ), void*来接近; a std function has both callable-ness and state, a function pointer only has callable-ness.标准 function 具有可调用性state,function 指针仅具有可调用性。 (std function also carries RTTI and how-to-cleanup-state and how-to-copy-state). (标准 function 还带有 RTTI 以及如何清理状态和如何复制状态)。

Now you can convert a void(*)() into a std function that is stronger;现在您可以将void(*)()转换为更强的 std function; but not the other way.但不是相反。 And the arguments to a function are converted the other way when the call happens.当调用发生时,arguments 到 function以另一种方式转换。

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

that is the rough C equivalent of a std::function<void(int32_t)> .这是粗略的 C 等效于std::function<void(int32_t)>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM