Convertir pointeur de fonction C++ à c de pointeur de fonction
Je développe une application C++ à l'aide d'une bibliothèque C de. J'ai envoyer un pointeur à la fonction de la bibliothèque C.
C'est ma classe:
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
void f(int*);
private slots:
void on_btn_clicked();
};
C'est mon on_btn_clicked fonction:
void MainWindow::on_btn_clicked()
{
void (MainWindow::* ptfptr) (int*) = &MainWindow::f;
c_library_function(static_cast<void()(int*)>(ptfptr), NULL);
}
La fonction C devriez obtenir un pointeur vers une fonction : void f(int*).
Mais le code ci-dessus ne fonctionne pas, je ne peux pas réussir à convertir ma f fonction de membre du pointeur souhaité.
Quelqu'un peut s'il vous plaît aider?
fonctions à l'intérieur d'une classe ne sont pas recommandés pour accéder aux.
double possible de la Fonction de pointeur de fonction membre de classe de problèmes
Votre question n'a aucun sens. Fonction C++ les pointeurs et C pointeurs de fonction sont la même chose (sauf pour certains mineurs de liaison de détails). Mais vous devez comprendre que
Pour débuter en C++ une fonction membre pour être utilisé comme un pointeur de fonction devrait être statique. Apportant C dans l'équation ne serait pas supprimer cette exigence.
Pour être 100% conforme aux normes (ce qui pourrait être pertinent pour les exotiques de matériel), vous devez utiliser un
double possible de la Fonction de pointeur de fonction membre de classe de problèmes
Votre question n'a aucun sens. Fonction C++ les pointeurs et C pointeurs de fonction sont la même chose (sauf pour certains mineurs de liaison de détails). Mais vous devez comprendre que
MainWindow::f
n'est pas une fonction et &MainWindow::f
n'est pas un pointeur de fonction, c'est un membre fonction (ou respectivement un pointeur vers une fonction membre).Pour débuter en C++ une fonction membre pour être utilisé comme un pointeur de fonction devrait être statique. Apportant C dans l'équation ne serait pas supprimer cette exigence.
Pour être 100% conforme aux normes (ce qui pourrait être pertinent pour les exotiques de matériel), vous devez utiliser un
extern "C"
fonction que le callback.OriginalL'auteur RRR | 2013-11-06
Vous devez vous connecter pour publier un commentaire.
Si je me souviens correctement, Seulement des méthodes statiques d'une classe peut être consulté via la "normale" C le pointeur de fonction de la syntaxe. Donc, essayez de la rendre statique. Le pointeur à une méthode d'une classe a besoin d'informations supplémentaires, telles que "l'objet" (ce) qui n'a pas de sens pour un pur C méthode.
La FAQ montré ici a une bonne explication et un possible (laid) la solution à votre problème.
OriginalL'auteur fritzone
Vous ne pouvez pas passer d'un non-membre statique pointeur de fonction comme une fonction ordinaire pointeur. Ils ne sont pas la même chose, et probablement même pas de la même taille.
Vous pouvez cependant (généralement) de passer un pointeur vers un statique fonction de membre par C. Habituellement, lorsque l'enregistrement d'un rappel dans une API en C, vous obtenez également de passer un "user data" qui est transmis en retour à votre fonction. Si vous pouvez faire quelque chose comme:
Puis de l'enregistrer votre rappel que
c'est à dire passer le pointeur d'instance à la méthode statique, et de l'utiliser comme une fonction de transmission.
À proprement parler pour une portabilité totale, vous devez utiliser une fonction déclarée
extern "C"
plutôt que d'un membre statique pour faire de votre transmission (déclaré comme unfriend
si nécessaire), mais dans la pratique je n'ai jamais eu de problèmes à l'aide de cette méthode à l'interface de code C++ avec GObject code, qui est C rappel-lourds.OriginalL'auteur Tristan Brindle
Vous ne pouvez pas passer un pointeur de fonction à un non-fonction membre statique. Ce que vous pouvez faire est de créer un statique ou fonction globale qui fait l'appel à un paramètre instance.
Voici un exemple que je trouve utile qui utilise une classe d'assistance avec deux membres: une fonction wrapper et une fonction de rappel qui appelle le wrapper.
Cela, vous pouvez stocker n'importe quel appelable, même les non-fonctions membres statiques (à l'aide de
std::bind
) et le convertir en un c-pointeur à l'aide de laCallback::callback
fonction. E. g:static void callback
devrait êtrestatic Ret callback
.Cette approche ne fonctionne que si vous voulez convertir une fonction membre de la plaine c pointeur de fonction de droite? Si vous avez deux ou trois, vous avez besoin de deux ou trois, en fonction wrapper de classe, parce que chaque classe wrapper magasins fonctionnent comme variable membre statique.
Comment pourrait-on faire ce travail pour le multithreading? J'ai posté une nouvelle question ici : stackoverflow.com/questions/41198854/...
N'est-ce aussi travailler pour plusieurs objets?
OriginalL'auteur Snps
@Snp réponse est grande. J'ai étendu avec une cafetière fonction qui crée un rappel, comme je l'ai toujours utiliser
void
rappels sans paramètres:À partir de là, vous pouvez créer votre plaine C de rappel à partir de l'intérieur de la classe ou n'importe où d'autre et ont le membre appelé:
OriginalL'auteur Thomas Fankhauser
J'ai une idée (pas tout à fait conforme à la norme, comme
extern "C"
est manquant):Vous aurez des problèmes si plusieurs instances de
MainWindow
sont instanciés.+
dansregisterCallback(+[](int* arg){instance->...});
veux dire? C'est du jamais vu.Il convertit le lambda objet d'un pointeur de fonction. Le lambda aide à prévenir la pollution de l'espace de noms (une définition de fonction & déclaration du moins).
N'est-ce pas inutile? J'ai pensé à un non-capture de lambda est implicitement convertible sur un pointeur de fonction.
Il n'y a pas besoin de capturer une variable globale. Pourquoi serait-il? Aussi loin que la conversion est concerné, vous avez peut-être raison, mais le
+
ne pas nuire autant que je sache.Je ne savais pas que c'était un mondial au premier abord.
OriginalL'auteur user1095108
La réponse courte est: vous pouvez convertir un pointeur de fonction membre ordinaire C pointeur de fonction à l'aide de std::mem_fn.
C'est la réponse à la question donnée, mais cette question semble avoir confondu prémisse, que la personne s'attend à ce code C pour être en mesure d'appeler une méthode d'une instance de MainWindow sans avoir une MainWindow*, qui est tout simplement impossible.
Si vous utilisez mem_fn de jeter
MainWindow::on_btn_clicked
vers un pointeur de fonction, vous avez encore une fonction qui prend unMainWindow*
en tant que premier argument.C'est la réponse à la question, mais il ne correspond pas à l'interface. Vous devez écrire une fonction C pour encapsuler l'appel à une instance spécifique (après tout, votre C code de l'API ne sait rien à propos de MainWindow ou de toute instance spécifique de celui-ci):
Ceci est considéré comme une OO anti-modèle, mais depuis l'API C ne sait rien au sujet de votre objet, c'est le seul moyen.
OriginalL'auteur stands2reason
@Snp réponse est parfait! Mais comme @DXM mentionné qu'il peut détenir qu'un seul rappel. J'ai amélioré un peu, maintenant, il peut garder de nombreux rappels du même type. C'est un peu étrange, mais fonctionne parfaitement:
Maintenant, vous pouvez simplement faire quelque chose comme ceci:
Est-il aussi une solution pour plusieurs objets? J'ai essayé cet exemple et il ne fonctionne pas correctement si j'ai plusieurs instances de "tf"
OriginalL'auteur Evgeniy Alexeev