Estou tentando criar um objeto estático escrito em Ir para interagir com um programa C (por exemplo, um módulo do kernel ou algo assim).
Encontrei documentação sobre como chamar funções C do Go, mas não encontrei muito sobre como seguir o outro caminho. O que eu descobri é que é possível, mas complicado.
Aqui está o que eu encontrei:
Postagem em blog sobre retornos de chamada entre C e Go
Postagem na lista de mala direta Golang
Alguém tem experiência com isto? Em resumo, estou tentando criar um módulo PAM totalmente escrito em Go.
c
shared-libraries
go
dynamic-linking
beatgammit
fonte
fonte
Respostas:
Você pode chamar o código Go de C. É uma proposição confusa.
O processo está descrito na postagem do blog ao qual você vinculou. Mas posso ver como isso não ajuda muito. Aqui está um pequeno trecho sem bits desnecessários. Isso deve tornar as coisas um pouco mais claras.
A ordem em que tudo é chamado é a seguinte:
A chave a lembrar aqui é que uma função de retorno de chamada deve ser marcada com o
//export
comentário no lado Go e comoextern
no lado C. Isso significa que qualquer retorno de chamada que você deseja usar deve ser definido dentro do seu pacote.Para permitir que um usuário do seu pacote forneça uma função de retorno de chamada personalizada, usamos exatamente a mesma abordagem acima, mas fornecemos o manipulador personalizado do usuário (que é apenas uma função Go normal) como um parâmetro que é passado para o C lado como
void*
. Ele é recebido pelo callbackhandler em nosso pacote e chamado.Vamos usar um exemplo mais avançado com o qual estou trabalhando atualmente. Nesse caso, temos uma função C que executa uma tarefa bastante pesada: lê uma lista de arquivos de um dispositivo USB. Isso pode demorar um pouco, por isso queremos que nosso aplicativo seja notificado sobre seu progresso. Podemos fazer isso passando um ponteiro de função que definimos em nosso programa. Ele simplesmente exibe algumas informações de progresso para o usuário sempre que são chamadas. Como possui uma assinatura conhecida, podemos atribuir a ele seu próprio tipo:
Esse manipulador leva algumas informações de progresso (número atual de arquivos recebidos e número total de arquivos) junto com um valor de interface {} que pode conter tudo o que o usuário precisar.
Agora precisamos escrever o encanamento C e Go para nos permitir usar esse manipulador. Felizmente, a função C que desejo chamar da biblioteca nos permite passar uma estrutura do tipo userdata
void*
. Isso significa que ele pode armazenar o que queremos, sem perguntas e vamos devolvê-lo ao mundo Go como está. Para fazer tudo isso funcionar, não chamamos a função de biblioteca de Go diretamente, mas criamos um wrapper C para o qual iremos nomeargoGetFiles()
. É esse wrapper que realmente fornece nosso retorno de chamada Go à biblioteca C, junto com um objeto userdata.Observe que a
goGetFiles()
função não aceita ponteiros de função para retornos de chamada como parâmetros. Em vez disso, o retorno de chamada que nosso usuário forneceu é empacotado em uma estrutura personalizada que contém o manipulador e o valor dos dados do usuário do usuário. Passamos isso paragoGetFiles()
o parâmetro userdata.É isso para as nossas ligações C. O código do usuário agora é muito direto:
Tudo isso parece muito mais complicado do que é. A ordem de chamada não mudou ao contrário do exemplo anterior, mas recebemos duas chamadas extras no final da cadeia:
A ordem é a seguinte:
fonte
Não é uma proposta confusa se você usar o gccgo. Isso funciona aqui:
foo.go
bar.c
Makefile
fonte
go package main func Add(a, b string) int { return a + b }
recebo o erro "undefined _go_string_plus"cgo
ego
nãogccgo
. Veja golang.org/cmd/cgo . Quando isso é dito, é totalmente possível usar o tipo "string" no arquivo .go e alterá-lo para incluir uma__go_string_plus
função. Isso funciona: ix.io/dZBA resposta mudou com o lançamento do Go 1.5
Esta pergunta que fiz há algum tempo aborda o problema novamente à luz dos 1,5 recursos adicionais
Usando o código Go em um projeto C existente
fonte
Para mim, não é possível:
fonte: https://github.com/golang/go/wiki/cgo
fonte