саша
В целом, конвертировать хз откуда данные в валидный go слайс — уже бида
в целом не иметь возможности этого сделать без потенциального уб — вот что хреново
Daniel
А?!
Daniel
Кто возможность отнял?
саша
Кто возможность отнял?
А она была? Или для вас это нормально, полагаться на "одинаковый" memory layout разных структур?
Daniel
Всегда была
Daniel
Называется (де)сериализация
Pawel
А как они это делают?
в смысле откуда берутся? внешняя прога посылает окну сообщение WM_COPYDATA, к нему прикрепляет данные
Pawel
такой вот способ межпроцессного обмена
саша
Называется (де)сериализация
а как вы десериализовать поинтер то собрались?
Daniel
А можно ее научить посылать protobuf?
Pawel
не, там жсон в строке
Anonymous
не, там жсон в строке
так JSON и go слайс вещи разные )) тогда уже разыменовать эту память и скормить декодеру, и структуры не нужны
Pawel
я не против, пытаюсь понять можно ли как-то разыменовать автоматически, или надо только побайтно
Pawel
C.GoBytes(unsafe.Pointer(x.LpData), C.int(x.DwData) ) - не работает
Daniel
а как вы десериализовать поинтер то собрались?
Я не люблю пустую болтовню, учтите
Daniel
не, там жсон в строке
Я имею в виду - там только указатель можно паснуть, или что угодно?
саша
так JSON и go слайс вещи разные )) тогда уже разыменовать эту память и скормить декодеру, и структуры не нужны
к тому же, на стеке ты точно не будешь это держать, ибо во время компиляции длинна не известна
Anonymous
только указатель конечно же
это все в рамках одного процесса, верно ?
Pawel
это все в рамках одного процесса, верно ?
один процес послылает другому процесу синхронно сообщение
Anonymous
один процес послылает другому процесу синхронно сообщение
Правильно ли Я понимаю, что один процесс посылает другому процессу просто указатель на кусок памяти (первого процесса) в сообщении этом ?
Pawel
именно так
Daniel
И указатель этот на слайс байтов, так?
Anonymous
именно так
это кусок heap ? оно же не будет работать
Pawel
И указатель этот на слайс байтов, так?
да. первая программа создаёт массив байтов, формирует сообщение с валидным указателем, и отправляет его синхронно в SendMessage, вторая программа в оконном цикле сообщений его принимает и забирает байты.
Pawel
тут важно понимать, если у вас и правда процессы ( а не потоки/горутины), то этот метод работь не будет
хватит этого. не надо мне рассказывать что рекомендованный способ обмена между процессами не работает
Anonymous
Почему это?
Потому что у каждого процесса своя виртуальная память, так сказать :) И указатель первого процесса не будет валидным для другого
Алексей
Потому что у каждого процесса своя виртуальная память, так сказать :) И указатель первого процесса не будет валидным для другого
Ну вообще-то как я понял речь идёт про специальное сообщение WM_COPYDATA, а его название как бы намекает на принцип его действия.
саша
Почему это?
Потому-что в линуксе разделяемая память между процессами есть только при форке, и то там Copy on Write. Ещё можно иметь разделяемую память через файловый дескриптор, но тут похоже другая история.
Anonymous
все, ухожу :D
Daniel
А оно достаточно умное, чтобы сделать прямое управление и для массива, на который слайс ссылается?
Pawel
честно говоря я хз. Но в сищных примерах это всё как-то работает
саша
честно говоря я хз. Но в сищных примерах это всё как-то работает
Короче, тебе нельзя это в слайс превращать, а то гошный рантайм попытается собрать мусор, за что его винда покарает.
Алексей
А оно достаточно умное, чтобы сделать прямое управление и для массива, на который слайс ссылается?
ну нет, слайс же ведь - это особая структура про которую виндовое сообщение ничего не знает
Roman
b := *(*[]byte)(unsafe.Pointer(&sl))
не будет работать
Алексей
ещё вроде бы wm_copydata имеет какие-то ограничения на длину сообщения, так что аккуратнее, хотя я могу и ошибаться
Anonymous
не будет работать
Да уже выяснили ... ))
Roman
пойнтер указывает на блок памяти известного размера, в котором например строка. Вот мне надо эту строку получить
func PtrSliceFrom(p unsafe.Pointer, s int) unsafe.Pointer { return unsafe.Pointer(&reflect.SliceHeader{Data: uintptr(p), Len: s, Cap: s}) }
Roman
дальше надо скастить в поинтер на слайс нужного типа.
саша
func PtrSliceFrom(p unsafe.Pointer, s int) unsafe.Pointer { return unsafe.Pointer(&reflect.SliceHeader{Data: uintptr(p), Len: s, Cap: s}) }
и упасть с ошибкой, когда гошный рантайм начнёт собирать мусор
саша
SEGMENTATION FAULT
саша
откуда ошибка?
Данные с другого процесса, read only access
Anonymous
откуда ошибка?
кусок памяти read-only
Roman
Данные с другого процесса, read only access
так не надо туда писать ничего.
саша
откуда ошибка?
Сделаешь free(ptr) и взрываешься
саша
так не надо туда писать ничего.
Как ты это гошному рантайму объяснишь?
Roman
Сделаешь free(ptr) и взрываешься
даже после free не взорвется. взрывается только на записи.
Roman
Как ты это гошному рантайму объяснишь?
рантайм ничего никуда не пишет.
Roman
это работает
да, потому что это из моего рабочего кода для netmap, где через mmap ядро дает тебе жирный кусок памяти.
Pawel
супер! большое спасибо
Roman
Как ты это гошному рантайму объяснишь?
можно с таким же успехом сделать b := *(*[4096]byte)(some_unsafe_pointer)
саша
рантайм ничего никуда не пишет.
ладно, не буду спорить о том, о чём не знаю, венда — тёмный лес
Roman
и если не выходить за границы, то все будет работать
Kirill
Kirill
@madgopher выручай
Ja-ja. Чё там?
Pawel
@madgopher да уж разобрались благодаря @pragus
Pawel
у меня есть значение uintptr. Как мне получить из него соответствующий []byte ?
Pawel
Ага)
Kirill
Вариант неплохой-то
Roman
Вариант неплохой-то
плохой, потому что надо контролировать длину ручками, ну и оно в компайл-тайме задает лимит.
Pawel
Через рефлекшн круче