[英]How to use C++ Function Pointer as Parameter to a C Funcion Pointer/Callback
I do know about C++ lambdas or C function pointers, but I don't know how to mix them together. 我确实了解C ++ lambda或C函数指针,但是我不知道如何将它们混合在一起。 I already found Mixing C++ instance methods with C callback functions , but it does not relies to my needs.
我已经发现将C ++实例方法与C回调函数混合在一起 ,但是它并不依赖于我的需求。
I have a C++ class the include C headers, like these: 我有一个包含C标头的C ++类,如下所示:
extern "C" {
#include <jack/jack.h>
#include <jack/types.h`enter code here`>
#include <jack/ringbuffer.h>
#include <jack/midiport.h>
}
#include <QDialog>
#include <QFile>
#include <QString>
#include "Cliente.h"
class FormQStudio : public QDialog
{
Q_OBJECT
public:
explicit FormQStudio(QWidget *parent = nullptr);
~FormQStudio();
void playMIDIFile(QString file) noexcept(false);
int theCallback(jack_nframes_t nframes, void *arg);
};
The C headers defines some types : C标头定义了一些类型:
typedef uint32_t jack_nframes_t;
typedef int (*JackProcessCallback)(jack_nframes_t nframes, void *arg);
int jack_set_process_callback (jack_client_t *client,
JackProcessCallback process_callback,
void *arg) JACK_OPTIONAL_WEAK_EXPORT;
The implementaion of my C++ class needs to pass theCallback(jack_nframes_t nframes, void *arg)
as a parameter to C function jack_set_process_callback
. 我的C ++类的实现需要将
theCallback(jack_nframes_t nframes, void *arg)
作为参数传递给C函数jack_set_process_callback
。 But I don't know how to do it. 但是我不知道该怎么做。
#include "FormQStudio.h"
FormQStudio::FormQStudio(QWidget *parent) :
QDialog(parent),
ui(new Ui::FormQStudio)
{
ui->setupUi(this);
}
void FormQStudio::playMIDIFile(QString file) noexcept(false){
smf_t *smf = smf_load(file.toUtf8());
smf_event_t *event;
Cliente *c = new Cliente("QStudio");
c->inicializarCliente(
/* HOW TO REFERENCE this->processJackCallback as a parameter? */
);
}
};
The class "Cliente" is this: 类“ Cliente”是这样的:
extern "C" {
#include <jack/jack.h>
#include <jack/types.h>
#include <jack/ringbuffer.h>
#include <jack/midiport.h>
}
#include <QString>
#include <QMap>
#include "ClientePorta.h"
#include "QStageException.h"
class Cliente
{
public:
Cliente(QString clientName);
struct MidiMessage {
jack_nframes_t time;
int len; /* Length of MIDI message, in bytes. */
unsigned char data[3];
};
jack_client_t *getClient();
void conectar(QString portaOrigem, QString clienteDestino, QString portaDestino) noexcept(false);
void inicializarCliente(JackProcessCallback callback) noexcept(false);
void addClientePorta(ClientePorta * cp);
ClientePorta* getClientePorta(QString nomePorta);
void sendMIDI(QString outputPortName, jack_nframes_t nframes ) noexcept(false);
private:
QString clientName;
QString inputPortName;
QString outputPortName;
QMap<QString,ClientePorta*> portas;
jack_client_t *jackClient = NULL;
};
The Cliente.cpp is: Cliente.cpp是:
#include "Cliente.h"
#include <QDebug>
Cliente::Cliente(QString clientName)
{
this->clientName = clientName;
}
void Cliente::inicializarCliente(JackProcessCallback callback) noexcept(false){
jackClient = jack_client_open(clientName.toUtf8().data(), JackNoStartServer, NULL);
int err = jack_set_process_callback(jackClient, callback , this);
}
};
I'm ommiting the rest of the implementation since it is not relevant. 我忽略了其余的实现,因为它不相关。 I'm also not asking about lib jack.
我也不是在问lib jack。 The focus is how to pass a C++ function as parameter to a C callback as show above.
重点是如何将C ++函数作为参数传递给C回调,如上所示。
Pay attention to the fact that the last parameter to jack_set_process_callback
() is a void *
, and it gets passed through to the callback function. 请注意,
jack_set_process_callback
()的最后一个参数是void *
,并且该参数将传递给回调函数。
This is a common design pattern with C libraries to make them usable with C++. 这是C库的一种常见设计模式,可使其在C ++中使用。
What you are going to do is pass this
of the object whose method you wish to invoke, as a callback, as the void *
with the callback pointer to an extern "C"
linkage wrapper function that takes the void *
, then reinterpret_cast
s it back to a class instance pointer, and then invokes its method, something like: 你所要做的是通过
this
,其方法要调用的对象,作为回调,为void *
与回调指向一个extern "C"
联动包装函数,它的void *
,那么reinterpret_cast
的IT回到类实例指针,然后调用其方法,类似于:
extern "C" {
int fwd_callback(jack_nframes_t nframes, void *arg)
{
FormQStudio *p=reintrerpret_cast<FormQStudio *>(arg);
return p->theCallback(nframes);
}
};
// ...
FormQStudio *some_object;
// ...
jack_set_process_callback(client, fwd_callback, reinterpret_cast<void *>(some_object));
Of course, it's on you to make sure that the some_object
still exist and is a valid object, when the callback gets invoked. 当然,当调用回调函数时,要确保
some_object
仍然存在并且是有效的对象,这是您的some_object
。
FormQStudio::theCallback
is not a function. FormQStudio::theCallback
不是函数。 It's a non-static member function, which means that it can only be called through an object of type FormQStudio
, a pointer to which is passed as this
to the function. 这是一个非静态成员函数,这意味着它只能通过类型的对象被称为
FormQStudio
,一个指针,其为通过, this
给该函数。
C doesn't know anything about C++ classes or class members. C对C ++类或类成员一无所知。 So it's not capable of calling such a function.
因此它无法调用此类函数。
Moreover, the &
operator applied to FormQStudio::theCallback
produces a "pointer-to-member-function" (PMF), which is not at all the same thing as a pointer to a function. 而且,应用于
FormQStudio::theCallback
的&
运算符会产生一个“指向成员函数的指针” (PMF),这与指向函数的指针完全不同。 (That's probably why you're seeing compiler errors, although it's hard to know exactly what you tried from the code sample in your question.) So even C++ programs couldn't use that as a stand-alone callback, although they could use the .*
/ ->*
syntax to invoke it with a provided class intance object reference/pointer.. (Note: these days it's better to use std::invoke
rather than the rather obscure operators.) (这可能是为什么您看到编译器错误的原因,尽管很难从问题的代码示例中确切知道您尝试了什么。)因此,即使C ++程序也不能将其用作独立的回调,尽管它们可以使用
.*
/ ->*
语法使用提供的类实例对象引用/指针来调用它。(注意:如今,最好使用std::invoke
而不是晦涩的运算符。)
If it turns out that FormQStudio::theCallback
doesn't actually use this
at all, then make it static
. 如果事实证明
FormQStudio::theCallback
实际上根本没有使用this
,则将其设置为static
。 Then you can take its address and use that as a function pointer. 然后,您可以获取其地址并将其用作函数指针。 (Although I think it's not guaranteed that C and C++ functions have the same calling conventions, so it's conceivable that you could still have problems passing it to a C function expecting a callback.)
(尽管我认为不能保证C和C ++函数具有相同的调用约定,所以可以想象,在将其传递给需要回调的C函数时仍然会遇到问题。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.