Estoy tratando de crear un objeto estático escrito en Ir a la interfaz con un programa en C (por ejemplo, un módulo del núcleo o algo así).
He encontrado documentación sobre cómo llamar a las funciones de C desde Go, pero no he encontrado mucho sobre cómo ir al otro lado. Lo que he encontrado es que es posible, pero complicado.
Aquí está lo que encontré:
Publicación de blog sobre devoluciones de llamada entre C y Go
Publicación de la lista de correo de Golang
¿Alguien tiene experiencia con esto? En resumen, estoy tratando de crear un módulo PAM escrito completamente en Go.
c
shared-libraries
go
dynamic-linking
beatgammit
fuente
fuente
Respuestas:
Puede llamar al código Go desde C. aunque es una propuesta confusa.
El proceso se describe en la publicación de blog a la que se vinculó. Pero puedo ver cómo eso no es muy útil. Aquí hay un fragmento corto sin partes innecesarias. Debería aclarar las cosas un poco.
El orden en que se llama todo es el siguiente:
La clave para recordar aquí es que una función de devolución de llamada debe marcarse con el
//export
comentario en el lado Ir yextern
en el lado C. Esto significa que cualquier devolución de llamada que desee utilizar debe definirse dentro de su paquete.Para permitir que un usuario de su paquete proporcione una función de devolución de llamada personalizada, utilizamos exactamente el mismo enfoque que el anterior, pero proporcionamos el controlador personalizado del usuario (que es solo una función Go normal) como un parámetro que se pasa al C lado como
void*
. Luego lo recibe el callbackhandler en nuestro paquete y se llama.Usemos un ejemplo más avanzado con el que estoy trabajando actualmente. En este caso, tenemos una función C que realiza una tarea bastante pesada: lee una lista de archivos desde un dispositivo USB. Esto puede llevar un tiempo, por lo que queremos que nuestra aplicación sea notificada de su progreso. Podemos hacer esto pasando un puntero de función que definimos en nuestro programa. Simplemente muestra información de progreso al usuario cada vez que se le llama. Como tiene una firma bien conocida, podemos asignarle su propio tipo:
Este controlador toma información de progreso (número actual de archivos recibidos y número total de archivos) junto con un valor de interfaz {} que puede contener cualquier cosa que el usuario necesite.
Ahora necesitamos escribir la tubería C y Go para permitirnos usar este controlador. Afortunadamente, la función C que deseo llamar desde la biblioteca nos permite pasar una estructura de tipo de datos de usuario
void*
. Esto significa que puede contener lo que queramos, sin hacer preguntas y lo devolveremos al mundo de Go tal como está. Para que todo esto funcione, no llamamos a la función de biblioteca directamente desde Go, sino que creamos un contenedor de C para el que nombraremosgoGetFiles()
. Es esta envoltura la que realmente proporciona nuestra devolución de llamada Go a la biblioteca C, junto con un objeto de datos de usuario.Tenga en cuenta que la
goGetFiles()
función no toma ningún puntero de función para devoluciones de llamada como parámetros. En cambio, la devolución de llamada que ha proporcionado nuestro usuario está empaquetada en una estructura personalizada que contiene tanto ese controlador como el valor de datos de usuario propio del usuario. Pasamos estogoGetFiles()
como el parámetro userdata.Eso es todo por nuestros enlaces C. El código del usuario ahora es muy sencillo:
Todo esto parece mucho más complicado de lo que es. El orden de las llamadas no ha cambiado en comparación con nuestro ejemplo anterior, pero recibimos dos llamadas adicionales al final de la cadena:
El orden es el siguiente:
fuente
No es una propuesta confusa si usa gccgo. Esto funciona aquí:
foo.go
bar.c
Makefile
fuente
go package main func Add(a, b string) int { return a + b }
me sale el error "undefined _go_string_plus"cgo
y engo
lugar degccgo
. Ver golang.org/cmd/cgo . Cuando se dice eso, es completamente posible usar el tipo de "cadena" en el archivo .go y cambiar su archivo .c para incluir una__go_string_plus
función. Esto funciona: ix.io/dZBLa respuesta ha cambiado con el lanzamiento de Go 1.5
Esta pregunta SO que hice hace algún tiempo aborda nuevamente el problema a la luz de las capacidades agregadas 1.5
Usando el código Go en un proyecto C existente
fuente
Por lo que a mí respecta, no es posible:
fuente: https://github.com/golang/go/wiki/cgo
fuente