如何将函数作为参数从 C 传递到 C++ 并返回到 C
Posted
技术标签:
【中文标题】如何将函数作为参数从 C 传递到 C++ 并返回到 C【英文标题】:How to pass function as a parameter from C to C++ and back to C 【发布时间】:2017-08-03 19:19:01 【问题描述】:设置:我正在构建一个包含 C 部分和 C++ 部分的架构。
在我的架构中,我有:
-
获取数据的 data_io(C) 将其发送到处理器回调并输出处理后的数据。
data_processor(C) 负责处理数据并按需更改。
决定使用哪个处理器的 settings_manager(C++)。
关系如下:
-
settings_manager 对象被实例化,在其内部使用默认处理器函数初始化 data_processor,然后初始化 data_io 向其发送 processing_callback_function(在 settings_manager 中定义,但在内部引用 data_processor 函数),然后用于处理data_io 启动时的数据。 (所以,data_io在初始化时只接收一次processing_callback_function,并不关心callback在里面做什么,它只是生成数据,调用processing_callback_function并输出处理后的数据)
在系统工作时,settings_manager 可能会决定更改处理的 data_processor 类型,因此它会更改 processing_callback_function 以调用不同的 data_processor 函数。(data_io 不知道并继续工作)
下面是基本实现:
data_io.c:
typedef void (* ProcessorCallback_t)(float *, int);
ProcessorCallback_t processorCallback;
data_io_init(ProcessorCallback_t callback)
processorCallback;
...init all other stuff like data pointer...
data_io_loop()
bufSize = readData(&data);
processorCallback(&data, bufSize);
writeData(&data, bufSize);
data_procesor.c:
void data_processor_init()
...initialization routine...
void data_processor_proc1(float *data, int bufSize)
...data process...
void data_processor_proc2(float *data, int bufSize)
...data process...
settings_manager.cpp:
void SettingsManager::start()
data_processor_init();
this->processing_function = &data_processor_proc1;
//THIS IS MY QUESTION! HOW TO PASS THE processing_callback_function TO data_io_init
data_io_init(&SettingsManager::processing_callback_function);
... here starts a new thread to run loop below...
//while(this->condition)
// data_io_loop();
//
void SettingsManager::changeProcessorType(int processorType)
switch(processorType)
case 1:
this->processing_function = &data_processor_proc1;
break;
case 2:
this->processing_function = &data_processor_proc2;
break;
void SettingsManager::processing_callback_function(float *data, int buffer_size)
this->processing_function(data, buffer_size);
我的问题:
1.我应该如何将 processing_callback_function C++ 成员函数传递给 data_io_init C 函数?
当我执行以下操作时:
data_io_init(&SettingsManager::processing_callback_function);
我收到以下错误:
"Incompatible pointer types 'ProcessorCallback_t' and 'void(Engine::*)(float*,int)'"
错误很明显,类型不同,因为第二个是成员函数并且是对象实例的一部分。
我读过我应该将 processing_callback_function 设为静态,但我不确定这是否是正确的方法。
-
处理此类事情的适当方法是什么,是否有任何可能对阅读有用的赞助人,或可能相关的编码策略?
【问题讨论】:
C 中的部分(为了获得最佳性能,无需类转换或多次耗时的内存解析)您对 C++ 的假设是错误的。 你是怎么编译这些文件的,SettingsManager
的定义是什么?
@manni66 请解释一下我很想学习,可以回答我的第二个问题
“C++ 对于时间关键部分来说太慢了”——现在这是核心。
@alexm 由于 C 几乎是 C++ 的一个子集,因此 C 代码不能比精心编写的 C++ 更快(除非您使用不同的编译器)。在最坏的情况下,性能将是相同的。为了让您的生活更轻松,您可以将所有内容编译为 C++。
【参考方案1】:
非静态类方法有一个隐藏的this
指针,而独立函数没有。因此,您不能传递需要独立函数的非静态类方法。
在这种情况下,最好的解决方案是允许 C++ 代码将用户定义的值传递给 C 代码,然后让 C 代码将该值传递回 C++ 代码。这样,C++ 代码就可以传递它的this
指针。例如:
data_io.h:
typedef void (* ProcessorCallback_t)(float *, int, void *);
void data_io_init(ProcessorCallback_t callback, void *userdata);
void data_io_loop();
data_io.c:
ProcessorCallback_t processorCallback;
void *processorUserData;
void data_io_init(ProcessorCallback_t callback, void *userdata)
processorCallback = callback;
processorUserData = userdata;
...init other stuff as needed ...
void data_io_loop()
...
processorCallback(&data, bufSize, processorUserData);
...
那么SettingsManager
可以这样做:
settings_manager.h:
typedef void (* ProcessorFunc_t)(float *, int);
class SettingsManager
private:
ProcessorFunc_t processing_function;
...
static void processing_callback_function(float *data, int buffer_size void *userdata);
public:
void start();
...
;
settings_manager.cpp:
#include "data_io.h"
void SettingsManager::start()
...
data_io_init(&SettingsManager::processing_callback_function, this);
...
void SettingsManager::processing_callback_function(float *data, int buffer_size void *userdata)
static_cast<SettingsManager*>(userdata)->processing_function(data, buffer_size);
或者这个(因为上面是技术上未定义的行为,但它确实在大多数编译器中工作。下面更符合标准):
settings_manager.h:
typedef void (* ProcessorFunc_t)(float *, int);
class SettingsManager
...
public:
ProcessorFunc_t processing_function;
void start();
...
;
settings_manager.cpp:
#include "data_io.h"
void processing_callback_function(float *data, int buffer_size void *userdata)
static_cast<SettingsManager*>(userdata)->processing_function(data, buffer_size);
void SettingsManager::start()
...
data_io_init(&processing_callback_function, this);
...
【讨论】:
【参考方案2】:1) 用 C++ 编写所有内容。使用 std::function 作为回调。这是处理此问题的最佳方法。你真的有性能问题吗?你量过吗? C++ 并没有那么慢。混合两种语言风格会带来的问题会带来更多的问题。
2) C 和 C++ 中的函数是相同的。您可以随时执行以下操作:
class Cls
public:
void callback()
;
void Cls_callback(void* ptr)
reinterpret_cast<Cls*>(ptr)->callback();
然后将 Cls_callback
作为 C 回调传递。
3) 您可以将Cls_callback
设为Cls
的静态方法,这样它就可以访问Cls
的私有成员:
class Cls
public:
static void Cls_callback(void* ptr)
Cls* self = reinterpret_cast<Cls*>(ptr);
self->i += 1;
private:
int i;
;
但请记住,这实际上是一个 UB。它会起作用,它的代码比变体 2 略少,但从技术上讲,标准并不能保证它会起作用。
附:再一次,不要混合风格。到处使用 C++。
【讨论】:
以上是关于如何将函数作为参数从 C 传递到 C++ 并返回到 C的主要内容,如果未能解决你的问题,请参考以下文章
从 C++ 调用 python 函数时如何将 C++ 类作为参数传递?