Appelez Go fonctions de C
Je suis en train de créer un objet statique écrit en revenir à l'interface avec un programme C (disons, un module de noyau ou de quelque chose).
J'ai trouvé de la documentation sur l'appel de fonctions C de Go, mais je n'ai pas trouvé beaucoup sur la façon d'aller dans l'autre sens. Ce que j'ai trouvé, c'est que c'est possible, mais compliqué.
Voici ce que j'ai trouvé:
Blog à propos des rappels entre C et
Golang liste de diffusion post
Quelqu'un a une expérience avec cela? En bref, je suis en train de créer un module PAM entièrement écrit en Aller.
- Vous ne pouvez pas, au moins à partir de fils qui n'ont pas été créés à partir de Aller. J'ai fait rage à propos de ce à de nombreuses reprises, et elle a cessé de développer en Aller jusqu'à ce que ce problème est résolu.
- J'ai entendu que c'est possible. N'est-il pas la solution?
- Go utilise une autre convention d'appel et de segmentation des piles. Vous pourriez être en mesure de relier Aller le code compilé avec gccgo avec du code C, mais je n'ai pas essayé car je n'ai pas réussi à gccgo de construire sur mon système.
- Je vais essayer à l'aide de SWIG maintenant, et je suis plein d'espoir... je n'ai pas rien eu à travailler encore que... ='( j'ai posté sur la liste de diffusion. J'espère que quelqu'un a pitié de moi.
- Vous pouvez appeler Aller de code C, mais pour le moment vous ne pouvez pas l'incorporer la Aller de l'exécution dans un C app, qui est un élément important, mais subtile différence.
- Que voulez-vous dire? Je suis totalement ok avec le fait d'avoir Aller courir dans son propre thread, mais je voudrais être en mesure de relier en Passer par du code C comme un objet partagé, et avoir un extérieur C appel de programme de la C wrappers, le C wrappers appel Aller, obtenir un résultat, puis retour à l'origine de la fonction. Je pense que je vais avoir à jouer avec les sockets pour le moment.
- Ce que je comprends, l'Aller runtime exige que certaines étapes d'initialisation d'un lieu qui n'a pas encore été prélevée dans une fonction que vous pouvez appeler à partir d'un exécutable. Il ya eu une discussion de cette question sur la liste de diffusion, même dans les dernières 24 heures. Mais j'imagine qu'il faudra un certain temps pour obtenir le droit, car vous pourriez potentiellement être polluantes de votre temps d'exécution existants et causant l'instabilité dans votre application hôte. Ça va venir, mais je ne voudrais pas retenir mon souffle.
- laisse l'haleine, je l'espère, c'est que tôt ou tard, parce que je pense que c'est une des choses qui de prime time.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez appeler le Go du code de C. c'est une source de confusion proposition si.
Le processus est décrit dans le billet de blog que vous avez associé. Mais je peux voir comment cela n'est pas très utile. Voici un court extrait sans inutiles bits. Il devrait rendre les choses un peu plus claires.
L'ordre dans lequel tout est appelée est comme suit:
La clé à retenir ici est qu'une fonction de rappel doit être marqué avec le
//export
commentaire sur l'Aller et queextern
sur le C côté. Cela signifie que tout de rappel que vous souhaitez utiliser, doit être définie à l'intérieur de votre colis.Afin de permettre à un utilisateur de votre colis, pour fournir une coutume fonction de rappel, nous utilisons exactement la même démarche que ci-dessus, mais nous fournissons à l'utilisateur du gestionnaire personnalisé (qui est juste un régulier de la fonction Go) comme un paramètre qui est passé sur le côté C comme
void*
. Il est ensuite reçu par le callbackhandler dans notre paquet et l'a appelé.Nous allons utiliser un exemple plus complexe, je suis actuellement en train de travailler. Dans ce cas, nous avons une fonction C qui effectue une lourde tâche: Il lit une liste de fichiers à partir d'un périphérique USB. Cela peut prendre un certain temps, nous voulons que notre application pour être informé de ses progrès. Nous pouvons le faire en passant un pointeur de fonction que nous avons défini dans notre programme. Il affiche simplement quelques progrès info à l'utilisateur chaque fois qu'il est appelé. Depuis qu'il a bien connu la signature, on peut lui assigner son propre type:
Ce gestionnaire prend des progrès info (nombre de dossiers reçus et le nombre total de fichiers) avec une interface{} valeur qui peut contenir tout ce que l'utilisateur en a besoin pour tenir.
Maintenant, nous avons besoin d'écrire du C et de plomberie pour nous permettre d'utiliser ce gestionnaire. Heureusement, la fonction C je souhaite appeler à partir de la bibliothèque nous permet de passer dans un userdata structure de type
void*
. Cela signifie qu'il peut contenir tout ce que nous voulons qu'il puisse tenir, sans poser de questions, et nous allons l'obtenir de nouveau dans la Aller le monde comme-est. Pour faire tout ce travail, nous n'avons pas appeler une fonction de la bibliothèque à partir d'y Aller directement, mais nous avons créer un wrapper C, ce qui nous permettra de nomgoGetFiles()
. C'est ce wrapper qui fait de fournitures de notre rendez-vous de rappel de la bibliothèque C, avec une userdata objet.Noter que le
goGetFiles()
fonction ne prend pas de pointeurs de fonction pour les rappels en tant que paramètres. Au lieu de cela, le rappel que notre utilisateur a fourni est emballé dans une coutume struct qui tient à la fois que le gestionnaire de l'utilisateur userdata de la valeur. Nous passons engoGetFiles()
en tant que paramètre userdata.Que pour notre C liaisons. Le code de l'utilisateur est maintenant très simple: le
Tout cela semble beaucoup plus compliqué qu'il ne l'est. L'ordre d'appel n'a pas changé contrairement à notre exemple précédent, mais nous avons deux appels supplémentaires à la fin de la chaîne:
De la commande comme suit:
Ce n'est pas une source de confusion proposition si vous utilisez gccgo. Ce qui fonctionne ici:
foo.aller
bar.c
Makefile
go package main func Add(a, b string) int { return a + b }
j'obtiens l'erreur "undefined _go_string_plus"cgo
etgo
au lieu degccgo
. Voir golang.org/cmd/cgo. Lorsque ce qui est dit, il est tout à fait possible d'utiliser la "chaîne" de type dans le .fichier aller et de changer votre .c fichier à inclure un__go_string_plus
fonction. Ceci fonctionne: ix.io/dZBLa réponse a changé avec la sortie de parcourir 1,5
Ce DONC, la question que j'ai demandé il y a quelques temps les adresses de nouveau cette question à la lumière de la 1.5 ajouté des capacités de
Utilisation de code dans un projet C
Autant que je suis concerné, il n'est pas possible:
source: https://github.com/golang/go/wiki/cgo