2013-04-08 14 views
31

Esistono alcuni tutorial o lezioni pratiche su come scrivere un'estensione per Ruby in Go?Scrittura di un'estensione Ruby in Go (golang)

+1

Non penso che questo avrebbe dovuto essere chiuso, ma scrivere un rubino l'estensione in Go è impossibile. C'è stato un po 'di lavoro su come creare estensioni python quando si incorpora l'interprete python in un programma Go. Lo stesso può essere fatto per Ruby. Ma al momento non puoi incorporare Go in un'altra lingua. –

+7

Il codice Go compilato con gccgo è richiamabile da C, quindi, per lo meno, è possibile scrivere la colla in C in modo tale che la maggior parte dell'estensione Ruby sia scritta in Go. Non so se è possibile saltare il livello di colla C, non sono sicuro. –

+4

Questa non è una domanda ridicola in quanto tale legame esiste per Python (http://gopy.qur.me/extensions/examples.html). Non è irragionevole per l'OP pensare che potrebbero esistere per Ruby. – voidlogic

risposta

64

Go 1.5 supporto aggiunto per la creazione di librerie condivise che possono essere richiamate da C (e quindi da Ruby tramite FFI). Questo rende il processo più semplice rispetto alle versioni precedenti alla 1.5 (quando era necessario scrivere il livello di colla C) e ora il runtime di Go è utilizzabile, rendendolo effettivamente utile nella vita reale (goroutine e allocazioni di memoria non erano possibili prima, come richiedono il runtime Go, che non era utilizzabile se Go non era il punto di ingresso principale).

goFuncs.go:

package main 

import "C" 

//export GoAdd 
func GoAdd(a, b C.int) C.int { 
    return a + b 
} 

func main() {} // Required but ignored 

Nota che il commento //export GoAdd è richiesto per ogni funzione esportata; il simbolo dopo export è il modo in cui la funzione verrà esportata.

goFromRuby.RB:

require 'ffi' 

module GoFuncs 
    extend FFI::Library 
    ffi_lib './goFuncs.so' 
    attach_function :GoAdd, [:int, :int], :int 
end 

puts GoFuncs.GoAdd(41, 1) 

La biblioteca è costruito con:

go build -buildmode=c-shared -o goFuncs.so goFuncs.go 

Esecuzione dello script di Ruby produce:

 
42 
+1

Funziona ancora se si eseguono allocazioni o Goroutine nel codice Go? – fuz

+0

@FUZxxl Ah, ora vedo il problema. Grazie per il chiarimento. –

+1

Ho seguito esattamente il tuo esempio per Go 1.5 e ha funzionato come un incantesimo, senza segoults per me. – AndrewH

11

Normalmente proverei a darti una risposta diretta ma i commenti fino ad ora dimostrano che potrebbe non essercene uno. Quindi, si spera che questa risposta con una soluzione generica e alcune altre possibilità siano accettabili.

Una soluzione generica: compilare un programma di linguaggio di alto livello nella libreria richiamabile da C. Avvolgere quello per Ruby. Uno deve essere estremamente attento all'integrazione a questo punto. Questo trucco è stato un bel trucco per integrare molte lingue in passato, di solito per motivi legacy. Il fatto è che non sono uno sviluppatore di Go e non so che puoi compilare Vai a qualcosa di chiamabile da C. Andando avanti.

Creare due programmi standalone: ​​Ruby e Go programma. Nei programmi, utilizzare un modo molto efficiente di passare i dati avanti e indietro. L'estensione stabilirà semplicemente una connessione al programma Go, invierà i dati, attenderà il risultato e passerà il risultato in Ruby. Il canale di comunicazione potrebbe essere IPC, socket, ecc. Qualunque supporto supporti. Il formato dei dati può essere estremamente semplice se non ci sono problemi di sicurezza e si utilizzano formati di messaggi predefiniti. Ciò aumenta ulteriormente la velocità. Alcuni dei miei vecchi programmi utilizzavano XDR per il formato binario. Oggigiorno, le persone sembrano usare cose come i protocolli JSON, Protocol Buffers e ZeroMQ.

Variazione del secondo suggerimento: utilizzare ZeroMQ! O qualcosa di simile. ZeroMQ è veloce, robusto e ha binding per entrambe le lingue. Gestisce l'intero paragrafo sopra per te. Gli svantaggi sono che è la regolazione delle prestazioni wrt meno flessibile e ha cose extra che non ti servono.

La parte difficile dell'utilizzo di due processi e il passaggio di dati tra di loro è una penalità di velocità. Il sovraccarico potrebbe non giustificare la partenza da Ruby. Tuttavia, Go ha grandi prestazioni native e funzionalità di concorrenza che potrebbero giustificare la codifica di parte di un'applicazione in esso rispetto a un linguaggio di scripting come Ruby. (Probabilmente una delle tue giustificazioni per la tua domanda.) Quindi, prova ognuna di queste strategie. Se ottieni un programma di lavoro che è anche più veloce, usalo. Altrimenti, rimani con Ruby.

Opzione forse meno accattivante: utilizzare qualcosa di diverso da Go che presenta vantaggi simili, consente di chiamare da C e può essere integrato. Anche se non è molto popolare, Ada è una possibilità. Da tempo è forte nel codice nativo, nella concorrenza (ristretta), nell'affidabilità, nel supporto di basso livello, nello sviluppo di linguaggi incrociati e IDE (GNAT). Inoltre, Julia è un nuovo linguaggio per la programmazione tecnica e parallela ad alte prestazioni che può essere compilato in una libreria richiamabile da C. Ha anche un JIT. Forse cambiare la dichiarazione del problema da Ruby + Vai a Ruby + (linguaggio più adatto) risolverà il problema?

+1

Puoi davvero compilare Vai a qualcosa chiamabile da C. Vedi questo articolo: http://golang.org/cmd/cgo/ – TSL

+0

Dolce! Quindi il richiedente ha molte opzioni con cui lavorare ora. :) –

2

Come di Go 1.5, c'è una nuova modalità di compilazione che dice al compilatore Go per generare una libreria condivisa e un file di intestazione C:

-buildmode c-shared 

(Questo è spiegato in modo più dettagliato in questo utile tutorial: http://blog.ralch.com/tutorial/golang-sharing-libraries/)

Con la nuova modalità di creazione, non è più necessario scrivere un livello di colla C da soli (come suggerito in precedenza nelle risposte precedenti). Una volta che hai la libreria condivisa e il file di intestazione, puoi usare FFI per chiamare la libreria condivisa creata da Go (esempio: https://www.amberbit.com/blog/2014/6/12/calling-c-cpp-from-ruby/)

Problemi correlati