Как стать автором
Поиск
Написать публикацию
Обновить

Комментарии 23

НЛО прилетело и опубликовало эту надпись здесь

Спасибо за статью, еще бы пункт "Из PHP" — цены бы не было))

pecl php ffi
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

КДПВ супер. А мне вот интересно, можно ли таки образом сделать библиотеку для С++ с легковесными горутинами внутри и скажем вызовом через cgo переданных std::function

Но зачем?
Вызов функции через cgo с ненулевой вероятностью создаст новый полноценный thread операционной системы, что убьёт всю лёгкость горутин.
НЛО прилетело и опубликовало эту надпись здесь
По опыту экспериментов с этим на Ruby, можно легко создавать в go коде gorutines, но надо дожидаться когда они завершатся, иначе будет segfault в конце. При этом прокинуть туда callback нельзя, видимо GIL и всякая другая обвязка над Ruby блоками не позволяет вызвать их. Вот на toster задавал еще тогда вопрос.
какое то «щиворот на выворот», обычно из go вызывают C/C++ методы
По мне в Ruby лучше написать нативное расширение, без динамической загрузки и поинтеров в ruby коде.
Минус FFI в том, что если выскакивает Exception в C, то все сразу падает, а в расширении хоть можно код обернуть и поймать ошибку и ничего не упадает.
Надо отметить, что я аналогичную задачу делал для Python, и при этом функция из библиотеки вызывалась как родная функция Python, без всяких cffi и с обработкой Python исключений. Но в целом статья хорошая.
Вызов Go методов из других языков разжеван уже донельзя. Вы бы лучше рассказали как там дела обстоят с возвращаемыми значениями (а здесь и начинаются настоящие приключения). Все работает очень гладко до тех пор пока мы не попробуем вернуть что-то посложнее строк или int.

Например вызывать метод Go из С++ и возвращать сложную структуру в теории нужно в такой последовательности:

1. В С++ аллоцировать структуру
2. Передать в Go поинтер
3. В Go заполнить значения структуры через C.types и unsafe.Pointer
4. В С++ проверить заполненность

И при этом очень легко нарваться на segfault.

А теперь представим что вместо вызова С -> Go, нам нужно вызвать Go -> С. Все становится еще веселее:

1. В Go (через CGo) нужно аллоцировать структуру (через написание отдельной функции в отдельном файле) и вернуть поинтер на нее.
2. В Go заполнить структуру через C.types и unsafe.Pointer
3. Передать unsafe.Pointer в C++
4. Скомпилировать эту матрешку (Go -> CGo -> Go -> C)

При этом шанс получить segfault возрастает экспоненциально.

А вся проблема в том что Go runtime любит очень быстро подчищать память. И если мы передали структуру собранную в Go напрямую, примерно на 2й инструкции в С она уже будет подчищена.
Вызывать то можно, но производительность при это не очень.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий