Pull to refresh

Comments 23

UFO just landed and posted this here

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

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

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

Вызов функции через cgo с ненулевой вероятностью создаст новый полноценный thread операционной системы, что убьёт всю лёгкость горутин.
UFO just landed and posted this here
По опыту экспериментов с этим на 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й инструкции в С она уже будет подчищена.
Вызывать то можно, но производительность при это не очень.
Sign up to leave a comment.