我在 C++ 中定义了两种类型的函数指针,如下所示:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
Class Core{
...
void myfunc1(LogFunction lg1, CallbackFn callback, int x, std::string y);
};
我希望能够在 C 中公开它们,但我似乎找不到办法做到这一点。我的第一次尝试是将它们投射为void*
然后将它们重新转换回实际类型。但这似乎是个坏主意。所以我对如何进行这种转换一无所知。
另外,我需要提出的解决方案至少应该可以使用 C++11 实现。
Update:
非常感谢您的回答。不过,我需要添加一些更多的解释作为我所追求的。我知道关于extern "C"
而事实上C++
函数已经在我的中使用它公开了DLL
。然而,我遇到的问题是通过函数指针在 C 和 C++ 之间来回切换。
一种方法是以 C 可以直接使用的方式定义函数指针。例如,我需要更改:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
与其 C 兼容的:
typedef void(*CCallbackFn)(bool, char*, int, unsigned char, int length);
typedef void(*CLogFunction)(char* string, int length);
并使用这些来代替。然而,这样做的缺点是,DLL 也被 C++ 客户端使用,这将成为将 C++ 的所有内容更改为 C 兼容的障碍,这样做会失去 C++ 的优点。
相反,我想到了第二种方法。 C++ 保持不变,但对于 C 链接以及通过 C API 与其他语言交互,我自己进行转换。
也就是说,他们使用 C 风格,然后我在实现部分将其转换回 C++。为了进一步简化,我还在 C++ 部分设计了一些默认值。意思是,假设由于缺乏更好的示例,实例需要一个回调函数来记录发生的任何情况。我定义了一个回调函数,以防用户未给出回调函数,并为 C API 创建两个函数,具体来说与此大致类似:
//in core.cpp for example
include "Core.h"
...
extern "C"
{
Core * core;
...
Core_API void* get_default_log_callback()
{
return (void*) core->SomeDefaultCallback();
}
Core_API void* set_log_callback(void* fn)
{
// convert/cast that to the c++ callback type
// CallbackFn,
core->SetCallback(fn_converted);
}
例如,客户端可以使用 get_default_log_callback 并使用其返回set_log_call_back
。
基本上,这里的想法是能够使用 C++ 已经定义的资产。
我陷入了这个转换过程,如何将此类回调指针转换为 C 兼容类型(就像我所展示的那样,将指针强制转换为 void* 并编写一个接受 void* 的 C 包装器真的很容易)然后将其重新转换为正确的类型。
我也想了解这种情况,以及这是否是一种好的做法,或者是一种不好的做法。
问题二:
我还想知道是否可以进行转换,例如CCallbackFn
and CallbackFn
?
假设我有一个函数(例如上面的 C 函数)CCalbackFn
形式,但我想最终把它放在CallbackFn
形式(更改它并调用接受的底层 C++CallbackFn
)?这可能吗 ?