我在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中完成。
更新:
非常感谢您的答案。但我需要补充一些说明,以便更清楚我的问题。我知道extern "C"
,实际上我的DLL
已经使用它公开了C++
函数。然而,我遇到的问题是在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 API进行交互的C链接,我自己进行转换。
这表示它们使用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 和 CallbackFn 进行转换?
假设我有一个以 CCalbackFn 形式表示的函数(例如上面的我的 C 函数),但我最终想要将其形式改为 CallbackFn(更改并调用支持 CallbackFn 的底层 C++)?这有可能吗?