Подтвердить что ты не робот

Написание расширения Ruby в Go (golang)

Есть ли некоторые уроки или практические уроки о том, как писать расширение для Ruby в Go?

4b9b3361

Ответ 1

Go 1.5 добавлена ​​поддержка для создания разделяемых библиотек, которые можно вызывать из C (и, следовательно, из Ruby через FFI). Это облегчает процесс, чем в версиях до 1.5 (когда необходимо было написать слой клея C), и теперь можно использовать время выполнения Go, что делает его действительно полезным в реальной жизни (раньше не могли быть выбраны распределения goroutines и памяти, так как они требуют времени выполнения Go, которое не использовалось, если Go не был основной точкой входа).

goFuncs.go:

package main

import "C"

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

func main() {} // Required but ignored

Обратите внимание, что комментарий //export GoAdd требуется для каждой экспортируемой функции; символ после export заключается в том, как будет экспортирована функция.

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)

Библиотека построена с помощью

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

Запуск Ruby script вызывает:

42

Ответ 2

Обычно я постараюсь дать вам прямой ответ, но комментарии пока показывают, что их может не быть. Итак, мы надеемся, что этот ответ с общим решением и некоторыми другими возможностями будет приемлемым.

Одно общее решение: скомпилируйте языковую программу высокого уровня в библиотеку, которую можно вызывать из C. Заверните, что для Ruby. На данный момент нужно очень внимательно относиться к интеграции. Этот трюк был хорошим клоком для интеграции многих языков в прошлом, как правило, по причинам, связанным с наследием. Дело в том, что я не разработчик Go, и я не знаю, что вы можете скомпилировать Go во что-то вызываемое из C. Перемещение.

Создайте две автономные программы: Ruby и Go. В программах используйте очень эффективный способ передачи данных вперед и назад. Расширение просто установит соединение с программой Go, отправит данные, дождитесь результата и передаст результат обратно в Ruby. Каналом связи может быть OS IPC, сокеты и т.д. Независимо от каждого поддерживаемого. Формат данных может быть чрезвычайно простым, если нет проблем с безопасностью, и вы используете предопределенные форматы сообщений. Это еще больше повышает скорость. Некоторые из моих старых программ использовали XDR для двоичного формата. В наши дни люди, похоже, используют такие вещи, как JSON, протокольные буферы и проводные протоколы в стиле ZeroMQ.

Изменение второго предложения: используйте ZeroMQ! Или что-то подобное. ZeroMQ быстрый, надежный и имеет привязки для обоих языков. Он управляет целым абзацем для вас. Недостатки в том, что он менее гибкий, и он не нуждается в дополнительных материалах.

Сложная часть использования двух процессов и передачи данных между ними - это ограничение скорости. Накладные расходы могут не оправдывать уход из Ruby. Однако Go имеет отличную производительность и concurrency функции, которые могут оправдывать кодирование части приложения в нем по сравнению с языком сценариев, например Ruby. (Возможно, одно из ваших обоснований для вашего вопроса.) Итак, попробуйте каждую из этих стратегий. Если вы получаете рабочую программу, которая также быстрее, используйте ее. В противном случае, придерживайтесь Ruby.

Возможно, менее привлекательный вариант: используйте что-то другое, кроме Go, которое имеет схожие преимущества, позволяет звонить с C и может быть интегрировано. Хотя это не очень популярно, Ада - это возможность. Он долго был сильным в собственном коде, (ограниченный) concurrency, надежность, поддержка низкого уровня, кросс-языковая разработка и IDE (GNAT). Кроме того, Julia - это новый язык для высокопроизводительного технического и параллельного программирования, который может быть скомпилирован в библиотеку, вызываемую с C. У нее есть JIT. Возможно, решение проблемы с Ruby + Go to Ruby + (более подходящий язык) решит проблему?

Ответ 3

Как и в случае Go 1.5, существует новый режим сборки, который сообщает компилятору Go для вывода общей библиотеки и файла заголовка C:

-buildmode c-shared

(Это объясняется более подробно в этом полезном учебнике: http://blog.ralch.com/tutorial/golang-sharing-libraries/)

В новом режиме сборки вам больше не нужно писать слой клея C (как ранее предполагалось в более ранних ответах). После того, как у вас есть разделяемая библиотека и заголовочный файл, вы можете перейти к использованию FFI для вызова общей библиотеки Go (см. Здесь: https://www.amberbit.com/blog/2014/6/12/calling-c-cpp-from-ruby/)