LINUX.ORG.RU

Сериализация данных в plain C

 ,


1

2

Как нынче модно в plain C выполнять сериализацию/десериализацию данных?

Ну то есть у меня какая-то структура, я хочу её записать в файл/отправить по сети. Значит мне нужно:

- Убрать выравнивание

- Переставить байтики под endiness (если не совпадает с endiness сериализации)

- Сделать то же самое для вложенных структур

- Вытащить динамические массивы (в самой структуре представлены двумя полями - длина и первый элемент) из кучи и положить их линейно с остальными полями

То есть прожиточный минимум - это либа, которая работает с байтовым буфером и имеет функции вида buffer_write_int8/buffer_write_int16/buffer_write_float32/buffer_read_int32/etc. Но если бы было можно пропарсить заголовочник с используемыми структурами (для меня ок, если будет требование все сериализуемые структуры держать в отдельных заголовочниках) и сгенерировать сериализаторы, либо наоборот сгенерировать структуры и сериазаторы из описания в каком-то другом формате, то было бы вообще шикарно.

Что я не хочу? Не хочу никакого оверхеда и метаинформации в сериализованных данных. Если я сериализую структуру из 3 int32_t, значит выходной буфер должен иметь размер строго 12 байт. Максимум можно опциональную фичу, отдельно включаемую для определённых структур, чтобы перед структурой писался её размер (типа чтобы при попытке десериализации старой версии структуры, новые поля проинициализировались нулями - подразумевается, что поля могут быть добавлены только в конец). Но я и без неё отлично проживу. И обязательно опциональная фича (потому что некоторые структуры точно не изменятся).

Так что всякие Protobuf не подходят, потому что помимо самих данных пишут всякую метаинформацию.

Удачный пример такой либы из плюсов - bitsery, но в plain C нет шаблонов и поэтому нужен другой подход к либе (кодогенерация).

★★★★★

Последнее исправление: KivApple (всего исправлений: 2)

Отправлять по сети незапакованные структуры Си с выравниваниями — это и есть оверхед. Protobuf позволяет сериализировать полупустую структуру из 3 int32_t как 3 байта! А ты будешь слать 12.

byko3y ★★★★
()

- Переставить байтики под endiness (если не совпадает с endiness сериализации)

живых архитектур без little endian почти не осталось

Harald ★★★★★
()

если у тебя этих структур не 100500, можно и ручками закодить всё

Harald ★★★★★
()
Ответ на: комментарий от KivApple

он имеет в виду выравнивание по размеру регистра/типа

зачем слать все 32 бита, если скажем значение в них умещается в первых 4

Harald ★★★★★
()

На вопрос как всегда не отвечу, но мнение имею.

- Убрать выравнивание

Сделать функции сериализации для базовых типов.

- Переставить байтики под endiness (если не совпадает с endiness сериализации)

Встроенные функции компилятора.

- Сделать то же самое для вложенных структур

- Вытащить динамические массивы (в самой структуре представлены двумя полями - длина и первый элемент) из кучи и положить их линейно с остальными полями

Сам.

Примерно так все будет:

struct st_name_xxx {
  int x;
  int y;
  const char *s;
  ...
};

struct st_name_yyy {
  struct st_name_xxx st;
};

/* create METAINFO_TYPE_st_name_xxx 

struct metainfo_t METAINFO_TYPE_st_name_xxx[] = { __BODY };

 */
DEFINE_METAINFO(st_name_xxx, {
  METAINFO_FIELD(/* offset */ x, /* name */ "x", /* srztype */ METAINFO_TYPE_INT), 
  METAINFO_FIELD(y, "y", METAINFO_TYPE_INT),
  METAINFO_FIELD(s, "s", METAINFO_TYPE_STR)
});

DEFINE_METAINFO(st_name_yyy, {
  METAINFO_FIELD(st, "st", METAINFO_TYPE_st_name_xxx)
});

Можно будет адаптировать под разные форматы. Компилятор оптимизирует что надо.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от anonymous

Какой еще вектор? Про Си говорим, если ты struct vector определил, то сделай для него define_metainfo и впиши в структуру его содержащую metainfo_field(..., METAINFO_TYPE_vector)

MOPKOBKA ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Какой еще вектор? Про Си говорим, если ты struct vector определил, то сделай для него define_metainfo и впиши в структуру его содержащую metainfo_field(…, METAINFO_TYPE_vector)

В простых случаях все просто …

anonymous
()

- Убрать выравнивание

Можно через #pragma pack или __attribute__((packed))

- Переставить байтики под endiness (если не совпадает с endiness сериализации)

См. https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html __ORDER_LITTLE_ENDIAN__ __ORDER_BIG_ENDIAN__

- Сделать то же самое для вложенных структур

Ну если у тебя структура в структуре описана - не вижу проблемы

- Вытащить динамические массивы (в самой структуре представлены двумя полями - длина и первый элемент) из кучи и положить их линейно с остальными полями

А для этого уже надо код какой-то писать.

Когда-то тут упоминали Kaitai Struct, но поддержку Си там так и не сделали. Cast GreyCat

SZT ★★★★★
()

Гуглите на github «flatbuffers» …

anonymous
()
Ответ на: комментарий от KivApple

Что ты подразумеваешь под «метаинформацией»? Всё что оно пишет на бинарном уровне – это один int в который упакован таг-номер поля и тип (field_number << 3) | wire_type и уже сами данные. Всё очень компактно и ничего лишнего.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 2)
Ответ на: комментарий от beastie

И с ним несложно работать …
Как вариант - вполне.

anonymous
()
Ответ на: комментарий от anonymous

Под asn.1 нет нормального сишного компилятора. Только полтора платных. Но если сменить си на эрланг, то да, вполне себе вариант.

beastie ★★★★★
()
Ответ на: комментарий от tnodir
struct Vec3 {
	x: float;
	y: float;
	z: float;
}

struct ClientMessage_UpdatePosition {
	position: Vec3;
	yaw: float;
	pitch: float;
}

union ClientMessageData {
	ClientMessage_UpdatePosition // To be added more messages
}

table ClientMessage {
	data: ClientMessageData;
}

Вот такая вот штука после сериализации FlatBuffers занимает 44 байта, хотя должна занимать 5 * sizeof(float) + enum для выбора типа сообщения = 24 байта (это если enum int, хотя это оверкилл и можно использовать числовой тип поменьше).

То есть оверхед 20 байт (почти 2 раза) на ровном месте.

KivApple ★★★★★
() автор топика
Последнее исправление: KivApple (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

С X-макросами код ещё поприятнее будет:

#define fields(T, meta, x) T x;
#define meta(T, meta, x) METAINFO_FIELD(x, #x, METAINFO_TYPE_##meta),

#define ST_NAME_XXX(_)     \
	_(int,         INT, x) \
	_(int,         INT, y) \
	_(const char*, STR, s)

#define ST_NAME_YYY(_) \
	_(struct st_name_xxx, st_name_xxx, st)

struct st_name_xxx {
	ST_NAME_XXX(fields)
};

struct st_name_yyy {
	ST_NAME_YYY(fields)
};

DEFINE_METAINFO(st_name_xxx, {
	ST_NAME_XXX(meta)
});

DEFINE_METAINFO(st_name_yyy, {
	ST_NAME_YYY(meta)
});
anonymous
()
Ответ на: комментарий от Harald

Там кустомная реализация, а не полный asn.1 компилятор. В принципе там ничего сложного нет. Протобаф на стероидах. Или точнее, протобаф – это лайт-вариант asn.1

Но для полной поддержки из открытого ничего нет. Полтора калеки.

beastie ★★★★★
()
Ответ на: комментарий от beastie

Не совсем так.

Под asn.1 нет нормального сишного компилятора. Только полтора платных. Но если сменить си на эрланг, то да, вполне себе вариант.

Плохая это идея с эрлангом. Рекомендую к ознакомлению. Неплох, весьма неплох.

Moisha_Liberman ★★
()
Ответ на: комментарий от KivApple
syntax = "proto3";

message ClientMessage {
	ClientMessageData data = 1;
}

message ClientMessageData {
	Vec3 position = 1;
	float yaw = 2;
	float pitch = 3;
}

message Vec3 {
	float x = 1;
	float y = 2;
	float z = 3;
}

Со всеми 5-ю параметрами выставленными в 1.0 выдаёт

0a 1b 0a 0f 0d 00 00 80 3f 15 00 00 80 3f 1d 00 00 80 3f 15 00 00 80 3f 1d 00 00 80 3f

29 байт. 5 байт (prefix 5-и значений) больше твоего идеала. Меньше, если только гонять голые floats.

А пустое сообщение (всё параметры в 0.0) вообще 0 байт.

Всё таки protobuf, asn.1 и компанию не дураки делали.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 4)
Ответ на: комментарий от beastie

По частям для нагядности

0a				# field 1 type 2 (length-delimited) ClientMessageData data
1b				# length 27
	0a			# field 1 type 2 (length-delimited) Vec3 position
	0f			# length 15
		0d		# field 1 type 5 (float32) X
		00 00 80 3f	# 1.0
		15		# field 2 type 5 (float32) Y
		00 00 80 3f	# 1.0
		1d		# field 3 type 5 (float32) Z
		00 00 80 3f	# 1.0
	15			# field 2 type 5 (float32) yaw
	00 00 80 3f		# 1.0
	1d			# field 3 type 5 (float32) pitch
	00 00 80 3f		# 1.0
beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от beastie

Ok.

Плавали, для «hello world» сойдёт.

Для всяких «околосвязных» и «околотелефонных» дел он тоже вполне годен. Ну а дальше уже как скажете. =)

Moisha_Liberman ★★
()
Ответ на: комментарий от beastie

У меня падает сборка proto-gen-c:

ADD_CUSTOM_COMMAND(OUTPUT protobuf-c/protobuf-c.pb.cc protobuf-c/protobuf-c.pb.h
                   COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
                   ARGS --cpp_out ${CMAKE_BINARY_DIR} -I${MAIN_DIR} ${MAIN_DIR}/protobuf-c/protobuf-c.proto)
FILE(GLOB PROTOC_GEN_C_SRC ${MAIN_DIR}/protoc-c/*.h ${MAIN_DIR}/protoc-c/*.cc )
ADD_EXECUTABLE(protoc-gen-c ${PROTOC_GEN_C_SRC} protobuf-c/protobuf-c.pb.cc protobuf-c/protobuf-c.pb.h)

(фрагмент из build-cmake/CMakeLists.txt от protobuf-c)

Как можно заметить, ожидается, что protoc сгенерирует файлы protobuf-c/protobuf-c.pb.cc и protobuf-c/protobuf-c.pb.h. Однако, в качестве аргумента --cpp_out ему передаётся просто ${CMAKE_BINARY_DIR}, а не ${CMAKE_BINARY_DIR}/protobuf-c. В результате файлы гененируется в корне каталога сборки, а не в подкаталоге protobuf-c и, соответственно, компилятор не может их найти, когда собирает proto-gen-c.

Я не могу понять, это баг в скрипте сборки protobuf-c или это я виноват сам - я собираю protoc через add_subdirectory (чтобы не требовать его установки в сборочную систему, потому что я хочу поддерживать не только линуксы, а на офтопике установка каждой библиотеки/утилиты это боль и мой проект требует только CMake и компилятора, а всё остальное собирает через add_subdirectory или качает бинарники с официальных сайтов средствами CMake, кросскомпиляция тоже не проблема - нижеприведённый скрипт запускается через add_custom_command и дочерний CMake, чтобы гарантированно собрать нативным тулчайном, в то время как сам проект может быть собран с помощью CMAKE_TOOLCHAIN_FILE):

set(BUILD_SHARED_LIBS OFF)
set(protobuf_BUILD_TESTS OFF)
add_subdirectory(lib/protobuf/cmake "${CMAKE_CURRENT_BINARY_DIR}/protobuf")

set(Protobuf_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/protobuf/src")
set(Protobuf_LIBRARIES libprotobuf)
set(Protobuf_PROTOC_LIBRARY libprotoc)
set(
		Protobuf_PROTOC_EXECUTABLE
		"${CMAKE_CURRENT_BINARY_DIR}/protobuf/${CMAKE_BUILD_TYPE}/protoc${CMAKE_EXECUTABLE_SUFFIX}"
		-I${Protobuf_INCLUDE_DIR}
)
add_subdirectory(../lib/protobuf-c/build-cmake "${CMAKE_CURRENT_BINARY_DIR}/protobuf-c")
add_dependencies(protoc-gen-c protoc)
KivApple ★★★★★
() автор топика
Последнее исправление: KivApple (всего исправлений: 1)
Ответ на: комментарий от KivApple

когда сборка падает она показывает ошибку и пишет доп инфо в файл

вы это инфу намеренно утаиваете да бы раздувать флейм?

anonymous
()

на «С» не принято заниматься овер-инжинирингом.

в заголовке пишешь v1 и далее шлёшь так чтобы работало на том для чего сделано и не ломало мозг. Как заработает, из заработанного, начинаешь фантазировать, но не ранее.

сериализация в json чревата тем что выскочит (а он выскочит) менеджер и потребует валидируемую json-scheme и прочее.

на С не решают глобальных проблем, оставляя это Грете Тунберг и прочим. Тебе надо передать данные из точки А в точку B ? вот и сделай это.

Если протокол/форматы заранее не определён ни в A ни в B, то не ипи мозг, делай как тебе проще, быстрее и надёжнее.

Оставь универсализм расту и схемам, пусть упарываются

MKuznetsov ★★★★★
()
Ответ на: комментарий от anonymous

Логи с офтопика, как с самой ущербной в плане установки библиотек и утилит системы:

-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/kiv/Projects/VoxelGameC/cmake-build-debug-mingw/host
Microsoft (R) Build Engine version 16.10.0+4242f381a for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

  Checking Build System
  Building Custom Rule C:/Users/kiv/Projects/VoxelGameC/host/lib/protobuf/cmake/CMakeLists.txt
  libprotobuf.vcxproj -> C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf\Release\libprotobuf.lib
  Building Custom Rule C:/Users/kiv/Projects/VoxelGameC/host/lib/protobuf/cmake/CMakeLists.txt
  libprotoc.vcxproj -> C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf\Release\libprotoc.lib
  Building Custom Rule C:/Users/kiv/Projects/VoxelGameC/host/lib/protobuf/cmake/CMakeLists.txt
  protoc.vcxproj -> C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf\Release\protoc.exe
  Generating protobuf-c/protobuf-c.pb.cc, protobuf-c/protobuf-c.pb.h
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(241,5): warning MSB8065: Custom build for item "C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\CMakeFiles\260aaf6a09e9ebc725b68682e302be9a\protobuf-c.pb.cc.rule" succeeded, but specified output "c:\users\kiv\projects\voxelgamec\cmake-build-debug-mingw\host\protobuf-c\protobuf-c\protobuf-c.pb.cc" has not been created. This may cause incremental build to work incorrectly. [C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf-c\protoc-gen-c.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(241,5): warning MSB8065: Custom build for item "C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\CMakeFiles\260aaf6a09e9ebc725b68682e302be9a\protobuf-c.pb.cc.rule" succeeded, but specified output "c:\users\kiv\projects\voxelgamec\cmake-build-debug-mingw\host\protobuf-c\protobuf-c\protobuf-c.pb.h" has not been created. This may cause incremental build to work incorrectly. [C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf-c\protoc-gen-c.vcxproj]
  Building Custom Rule C:/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/build-cmake/CMakeLists.txt
  c_bytes_field.cc
  c_enum.cc
  c_enum_field.cc
  c_extension.cc
  c_field.cc
  c_file.cc
  c_generator.cc
  c_helpers.cc
  c_message.cc
  c_message_field.cc
  c_primitive_field.cc
  c_service.cc
  c_string_field.cc
  protobuf-c.pb.cc
c1xx : fatal error C1083: Impossible d'ouvrir le fichier sourceя: 'C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf-c\protobuf-c\protobuf-c.pb.cc'я: No such file or directory [C:\Users\kiv\Projects\VoxelGameC\cmake-build-debug-mingw\host\protobuf-c\protoc-gen-c.vcxproj]
  Generation de code en cours...
mingw32-make[3]: *** [CMakeFiles\gen_voxel_protocol.dir\build.make:81: host/protobuf-c/protoc-gen-c.exe] Error 1
mingw32-make[2]: *** [CMakeFiles\Makefile2:646: CMakeFiles/gen_voxel_protocol.dir/all] Error 2
mingw32-make[1]: *** [CMakeFiles\Makefile2:712: CMakeFiles/VoxelGameC.dir/rule] Error 2
mingw32-make: *** [Makefile:230: VoxelGameC] Error 2

Логи из-под Ubuntu в WSL:

-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/c/Users/kiv/Projects/VoxelGameC/build/host
[ 44%] Built target libprotobuf
[ 89%] Built target libprotoc
[ 90%] Built target protoc
[ 90%] Generating protobuf-c/protobuf-c.pb.cc, protobuf-c/protobuf-c.pb.h
Scanning dependencies of target protoc-gen-c
[ 91%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_bytes_field.cc.o
[ 91%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_enum.cc.o
[ 93%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_enum_field.cc.o
[ 93%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_extension.cc.o
[ 93%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_field.cc.o
[ 94%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_file.cc.o
[ 94%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_generator.cc.o
[ 95%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_helpers.cc.o
[ 95%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_message.cc.o
[ 96%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_message_field.cc.o
[ 96%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_primitive_field.cc.o
[ 97%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_service.cc.o
[ 97%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/c_string_field.cc.o
[ 98%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/mnt/c/Users/kiv/Projects/VoxelGameC/lib/protobuf-c/protoc-c/main.cc.o
[ 98%] Generating protobuf-c/protobuf-c.pb.cc, protobuf-c/protobuf-c.pb.h
[ 98%] Building CXX object protobuf-c/CMakeFiles/protoc-gen-c.dir/protobuf-c/protobuf-c.pb.cc.o
c++: error: /mnt/c/Users/kiv/Projects/VoxelGameC/build/host/protobuf-c/protobuf-c/protobuf-c.pb.cc: No such file or directory
c++: fatal error: no input files
compilation terminated.
make[6]: *** [protobuf-c/CMakeFiles/protoc-gen-c.dir/build.make:252: protobuf-c/CMakeFiles/protoc-gen-c.dir/protobuf-c/protobuf-c.pb.cc.o] Error 1
make[5]: *** [CMakeFiles/Makefile2:234: protobuf-c/CMakeFiles/protoc-gen-c.dir/all] Error 2
make[4]: *** [CMakeFiles/Makefile2:241: protobuf-c/CMakeFiles/protoc-gen-c.dir/rule] Error 2
make[3]: *** [Makefile:238: protoc-gen-c] Error 2
make[2]: *** [CMakeFiles/gen_voxel_protocol.dir/build.make:63: host/protobuf-c/protoc-gen-c] Error 2
make[1]: *** [CMakeFiles/Makefile2:769: CMakeFiles/gen_voxel_protocol.dir/all] Error 2
make: *** [Makefile:152: all] Error 2

Повторю, проблема в том, что protobuf-c.pb.cc и protobuf-c.pb.h сгенерированы в ${CMAKE_BINARY_DIR}/protobuf-c, а не в ${CMAKE_BINARY_DIR}/protobuf-c/protobuf-c, которые прописаны в списке исходников исполняемого файла в CMake. Я привёл в своём предыдущем сообщении конткетный фрагмент CMakeLists.txt от protobuf-c, который за это отвечает.

Кстати, мой собственный CMakeLists.txt немного изменился, чтобы стать более кроссплатформенным, однако это сути не меняет и ошибка проявляется на всех платформах.

cmake_minimum_required(VERSION 3.12)
project(VoxelGameC-host)

set(BUILD_SHARED_LIBS OFF)
set(protobuf_BUILD_TESTS OFF)
add_subdirectory(lib/protobuf/cmake "${CMAKE_CURRENT_BINARY_DIR}/protobuf")

set(Protobuf_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/protobuf/src")
set(Protobuf_LIBRARIES libprotobuf)
set(Protobuf_PROTOC_LIBRARY libprotoc)
if(MSVC)
	set(
			Protobuf_PROTOC_EXECUTABLE
			"${CMAKE_CURRENT_BINARY_DIR}/protobuf/${CMAKE_BUILD_TYPE}/protoc${CMAKE_EXECUTABLE_SUFFIX}"
			-I${Protobuf_INCLUDE_DIR}
	)
else()
	set(
			Protobuf_PROTOC_EXECUTABLE
			"${CMAKE_CURRENT_BINARY_DIR}/protobuf/protoc${CMAKE_EXECUTABLE_SUFFIX}"
			-I${Protobuf_INCLUDE_DIR}
	)
endif()

add_subdirectory(../lib/protobuf-c/build-cmake "${CMAKE_CURRENT_BINARY_DIR}/protobuf-c")
add_dependencies(protoc-gen-c protoc)
KivApple ★★★★★
() автор топика
Последнее исправление: KivApple (всего исправлений: 2)
Ответ на: комментарий от beastie
protoc-gen-c: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--c_out: protoc-gen-c: Plugin failed with status code 1.

Не всё так просто. Ему нужно, чтобы был собранный protoc-gen-c, а он в свою очередь не собирается (см. логи выше).

KivApple ★★★★★
() автор топика
Ответ на: комментарий от KivApple

Мне хватило

brew install protobuf-c

И чем

apt-get install protobuf-c-compiler

не подходит? Оно уже опакечено скорее всего везде.

beastie ★★★★★
()
Ответ на: комментарий от beastie

Мне сейчас нравится, что мой проект требует только установленного CMake и GCC/MSVC.

Все зависимости либо собираются из гит сабмодулей, либо (для SDL2, со сборкой которого у меня были небольшие проблемы) качаются бинарники для Windows с официального сайта в момент сборки проекта (разумеется, второй раз они уже не качаются, если не делать clean).

flatcc нормально собрался, а вот protobuf-c пока сложности.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от beastie

А в WSL без кросскомпиляции соберёт нативное Win приложение?

u-235
()
Ответ на: комментарий от KivApple

У меня нет Windows, проверить сборку там. Могу проверить на Mac и OpenBSD (у меня нет даже Linux).

А так это конечно вопрос философский. Вместо того, чтобы пердолиться со всеми зависимостями, я предпочитаю просто список requirements.

И в общем случае protobuf компилятор не является явной зависимостью. Скомрилированные файлы просто добавляются в проект, а не пересобираются каждый раз при сборке. (Даёт более повторяемый результат, весь авто-ген – часть кода.)

Т.е. это в лучшем случае dev-зависимость, но ни как не build-зависимость. Посему не вижу смысла собирать это каждый раз.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 4)
Ответ на: комментарий от beastie

ТС сказал, цитирую:

Ну то есть у меня какая-то структура, я хочу её записать в файл/отправить по сети

Всё остальное - его домыслы. Если он собирается передавать по сети в голом сокете сотни гигабайт, то его выбор - torrent, DC, eDonkey и прочие с чанками и контрольными суммами. Если он передает данные объемом 1-10 МБ, то оверхед у конверсии json (минифицированного) будет в пределах статистической погрешности. Зато:

  • Стандартизированный формат
  • Миллионы библиотек поддержки, своя реализация пишется за час
  • Любой уровень вложенности, массивы и объекты в комплекте.
PPP328 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.