我有一些返回的C++代码std::function.我想从一些C代码中调用它.这可能吗?作为一个例子,我有以下代码:
typedef std::function<int(int)> AdderFunction;
AdderFunction makeAdder(int amount) {
return [amount] (int n) {
return n + amount;
};
}
extern "C" {
AdderFunction makeCAdder(int amount) {
return makeAdder(amount);
}
}
Run Code Online (Sandbox Code Playgroud)
与clang++ -std=c++11 test.cpp它导致以下警告:
'makeCAdder' has C-linkage specified, but returns user-defined type 'AdderFunction' (aka 'function<int (int)>') which is incompatible with C
Run Code Online (Sandbox Code Playgroud)
我明白为什么会这样,但想知道是否有一种模式可以实现这一目标?
R S*_*ahu 15
C/C++之间最便携的接口方法是使用指针在语言之间传递数据,并使用非成员函数进行函数调用.
.h文件:
#ifdef __cplusplus
extern "C" {
#endif
// Declare the struct.
struct Adder;
// Declare functions to work with the struct.
Adder* makeAdder(int amount);
int invokeAdder(Adder* adder, int n);
void deleteAdder(Adder* adder);
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
在.cpp文件中实现它们:
#include <functional>
typedef std::function<int(int)> AdderFunction;
struct Adder
{
AdderFunction f;
};
AdderFunction makeAdderFunction(int amount) {
return [amount] (int n) {
return n + amount;
};
}
Adder* makeAdder(int amount)
{
Adder* adder = new Adder;
adder->f = makeAdderFunction(amount);
return adder;
}
int invokeAdder(Adder* adder, int n)
{
return adder->f(n);
}
void deleteAdder(Adder* adder)
{
delete adder;
}
Run Code Online (Sandbox Code Playgroud)
无法std::function从C 调用,因为C不支持所需的语言功能.C没有模板,访问修饰符,可调用对象,虚拟方法或其他任何std::function可以在引擎盖下使用的东西.您需要提出C可以理解的策略.
一种这样的策略是复制/移动std::function到堆并将其作为不透明指针返回.然后,您将通过C++接口提供另一个函数,该函数接受该不透明指针并调用它包含的函数.
// C side
struct function_opaque;
int call_opaque(struct function_opaque*, int param);
// C++ side
extern "C" {
struct function_opaque {
std::function<int(int)> f;
};
int call_opaque(function_opaque* func, int param) {
return func->f(param);
}
};
Run Code Online (Sandbox Code Playgroud)
当然,这会带来内存管理的影响.
extern "C"您需要至少将 typedef 放入块内(以使其编译为 C++)。不过,我不确定这在 C 中是否有效。在 C 中可行的就是使用普通函数指针,例如
extern "C" {
using AdderFunction = int(int);
// old-style: typedef int(*AdderFunction)(int);
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果您使用为您提供std::function对象的 API,则可以使用该std::function::target()方法来获取它引用的(可 C 调用的)原始函数指针。
using AdderFunction = std::function<int(int)>;
extern "C" {
using CAdderFunction = int(int);
CAdderFunction makeCAdder(int amount)
{
return makeAdder(amount).target<CAdderFunction>();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2755 次 |
| 最近记录: |