我已经在几个序列化协议之间进行了一些性能比较,包括FlatBuffers,Cap'n Proto,Boost序列化和谷物.所有测试都是用C++编写的.
我知道FlatBuffers和Cap'n Proto使用零拷贝.使用零拷贝时,序列化时间为空,但序列化对象的大小更大.
我认为谷物和Boost序列化没有使用零拷贝.但是,序列化时间(对于int和double)几乎为空,序列化对象的大小几乎与Cap'n Proto或Flatbuffers对象相同.我没有在他们的文件中找到任何有关零拷贝的信息.
谷物和Boost序列化也使用零拷贝吗?
我正在开发的项目是一个管理大量自定义硬件设备的C++应用程序.该应用程序具有客户端的套接字/端口接口(如GUI).每种设备类型都有自己定义良好的JSON模式,我们可以使用Cereal对这些模式进行序列化.
但该应用程序还需要解析来自客户端的入站JSON请求.请求的一部分指定设备过滤器参数,大致类似于SQL'WHERE'子句,其中所有表达式都是AND.例如:
"filter": { "type": "sensor", "status": "critical" }
Run Code Online (Sandbox Code Playgroud)
这将指示客户端想要在具有"关键"状态的每个"传感器"设备上执行操作.从表面上看,似乎过滤器参数的C++实现将是std :: map.但是当我们尝试使用Cereal反序列化它失败的对象时.当我们序列化硬编码的过滤器映射时,它看起来像这样:
"filter": [
{ "key": "type", "value": "sensor" },
{ "key": "status", "value": "critical" }
]
Run Code Online (Sandbox Code Playgroud)
现在我可以理解为什么Cereal支持这种详细的地图序列化.毕竟,地图的关键字可以是非字符串类型.但在这种情况下,键是一个字符串.
我并不十分热衷于重写我们的界面规范,并让我们的客户生成明显非惯用的JSON,以满足Cereal.我是谷歌的新手,我们坚持这一点.有没有办法告诉Cereal将此过滤器解析为std :: map?或者我可能是错误的方式.是否还有其他一些我们应该反序列化的stl容器?
我有四个类(A
,B
,C
和D
经典的金刚石图案和以下)Container
含有类unique_ptr<A>
.我想使用谷物序列化库序列化这些类.
struct A {int f1; int f2; int f3}
struct B : public virtual A {
template<typename Archive>
inline void save(Archive& ar) const {
std::cerr << "Saving Obj: " << this << std::endl;
std::cerr << "This: " << &(this->f1) << " "
<< &(this->f2) << " " << &(this->f3) << std::endl;
std::cerr << "This: " << this->f1 << " "
<< this->f2 << " " << …
Run Code Online (Sandbox Code Playgroud) 可以/如何使用谷物库序列化数组.
即
void save(Archive & ar, const unsigned int version) const
{
unsigned int l = g1_size_bin(g,POINT_COMPRESS);
uint8_t data[l];
memset(data, 0, l);
g1_write_bin(data, l, g,POINT_COMPRESS);
ar(l);
ar(data); // what should be here
}
Run Code Online (Sandbox Code Playgroud)
这不起作用(我也不期望它).也没有
ar(cereal::binary_data(data,l));
Run Code Online (Sandbox Code Playgroud)
(我认为它会工作,因为它看起来像一个人会使用的增强代码),这会产生编译错误:
/usr/local/include/cereal/cereal.hpp:79:17:注意:候选模板被忽略:替换失败:可变修改类型'unsigned char(&)[l]'不能用作模板参数BinaryData binary_data(T && data,size_t size)
也没有
ar.saveBinaryValue(data,l);
Run Code Online (Sandbox Code Playgroud)
由于该方法似乎只支持XML/Json,我想要一个二进制存档.
我正在使用Cereal C++ v1.1.1,类似于我正在尝试以下文档中给出的示例:
#include <sstream>
#include <iostream>
#include <cereal/archives/json.hpp>
int main() {
std::ostringstream os;
cereal::JSONOutputArchive archive(os);
int x = 12;
archive(CEREAL_NVP(x));
std::cout << os.str(); // JUST FOR DEMONSTRATION!
}
Run Code Online (Sandbox Code Playgroud)
我希望有以下内容:
{
"x":12
}
Run Code Online (Sandbox Code Playgroud)
但是结束的大括号丢失了.知道代码中缺少什么吗?
更新:
添加archive.finishNode()
似乎解决了问题.但我会说这不是解决方案.根据operator()
文档,调用操作符序列化输入参数,为什么要添加finishNode
额外的?
是否可以boost::ptr_vector
使用谷物序列化实例?如果是这样,怎么样?
*我知道有很多关于此的问题,但在谈论 CMake 时它们根本没有多大帮助,因此我决定提出这个问题*
因此,我正在研究 CLion,它使用 CMake 来导入并向编译器提供参数,并成功包含(导入)位于名为“ExternalLibraries”的文件夹中的外部库(cereal:将类序列化为 json 文件)我的项目文件夹的根目录。它工作得很好,直到我重新启动 IDE 并尝试再次运行代码...它返回了编译错误(我认为)。
我的 CMake 文件如下所示:
cmake_minimum_required(VERSION 3.3)
project(xMemory)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories ("${PROJECT_SOURCE_DIR}/ExternalLibraries/cereal-1.1.2/include/")
set(SOURCE_FILES main.cpp xObject.cpp xObject.h)
add_executable(xMemory ${SOURCE_FILES})
target_link_libraries (xMemory cereal)
Run Code Online (Sandbox Code Playgroud)
当我尝试运行/编译时,shell 给了我这个:
/home/lunaticsoul/Documents/clion-1.2.4/bin/cmake/bin/cmake --build /home/lunaticsoul/.CLion12/system/cmake/generated/95701c38/95701c38/Debug0 --target xMemory -- -j 4
Scanning dependencies of target xMemory
[ 33%] Building CXX object CMakeFiles/xMemory.dir/xObject.cpp.o
[ 66%] Building CXX object CMakeFiles/xMemory.dir/main.cpp.o
[100%] Linking CXX executable xMemory
/usr/bin/ld: cannot find -lcereal
collect2: error: ld returned 1 exit status
make[3]: *** [xMemory] Error 1
make[2]: …
Run Code Online (Sandbox Code Playgroud) 我有一个模板化的基类:
template<typename T>
class A {
public:
T a;
template<class Archive>
void serialize(Archive & ar) {
ar(a);
}
};
Run Code Online (Sandbox Code Playgroud)
以及从中派生的模板化类:
template<typename T>
class B : public A<T> {
public:
T b;
template<class Archive>
void serialize(Archive & ar) {
ar(cereal::base_class<A<T>>(this));
ar(b);
}
};
Run Code Online (Sandbox Code Playgroud)
它在另一个序列化类中使用:
template<typename T>
class C {
template<class Archive>
void serialize(Archive & ar)
{
ar(collection);
}
std::vector<std::shared_ptr<A<T>>> collection;
};
Run Code Online (Sandbox Code Playgroud)
该代码和使用它的代码被编译成静态库
根据我对谷物文档的理解,我需要添加
CEREAL_REGISTER_TYPE(A<double>)
CEREAL_REGISTER_TYPE(A<float>)
CEREAL_REGISTER_TYPE(B<double>)
CEREAL_REGISTER_TYPE(B<float>)
Run Code Online (Sandbox Code Playgroud)
在每个类的头文件中,对于将要使用的每种类型等
这样编译。但是运行时错误为
尝试保存未注册的多态类型(B)。在调用CEREAL_REGISTER_TYPE之前,请确保您的类型已在CEREAL_REGISTER_TYPE中注册,并且已包含您正在使用的档案(并已在CEREAL_REGISTER_ARCHIVE中注册)。如果您的类型已经注册,但仍然看到此错误,则可能需要使用CEREAL_REGISTER_DYNAMIC_INIT。
从文档中,我认为我需要CEREAL_FORCE_DYNAMIC_INIT(libname)
在标题和CEREAL_REGISTER_DYNAMIC_INIT
CPP文件中添加,但是没有cpp文件。或一个合适的CPP文件来放置它。
添加CEREAL_REGISTER_POLYMORPHIC_RELATION
没有任何变化,因为B
的序列化函数正在使用调用基函数A …
我希望得到一种模板化的方法来查找类型是否为shared_ptr,并且基于我希望有一个新的函数特化.
示例主要功能是,
template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME( RelaxedJSONInputArchive & ar, NameValuePair<T> & t )
{
std::cout << " CEREAL_LOAD_FUNCTION_NAME NameValuePair 1 " << std::endl;
ar.setNextName( t.name );
ar( t.value );
}
Run Code Online (Sandbox Code Playgroud)
如果t.value是shared_ptr,那么我想要一个不同的函数特化.我试过下面,
template <class T> inline
typename std::enable_if<is_pointer<T>::value, void>::type
CEREAL_LOAD_FUNCTION_NAME( RelaxedJSONInputArchive & ar, NameValuePair<T> & t )
{
std::cout << " CEREAL_LOAD_FUNCTION_NAME NameValuePair 2 " << std::endl;
ar.setNextName( t.name );
ar( t.value );
}
Run Code Online (Sandbox Code Playgroud)
但它似乎没有用.这些是c ++ 11谷物库的一部分.我正在尝试自定义.
我已经在github上问了这个问题(大约一个月前),没有任何答案,所以我现在在这里问。
我在项目中使用Cereal作为序列化库。我尝试添加序列化功能std::string_view
(基本上是从std::string
实现中复制和粘贴)。但是,Cereal会引发编译器错误:
谷物找不到提供的类型和档案组合的任何输出序列化功能。
这是我的实现(我在这里禁用了反序列化,但是我也尝试了一个伪函数,它给了我相同的结果):
#pragma once
#include "../cereal.hpp"
#include <string_view>
namespace cereal
{
//! Serialization for basic_string_view types, if binary data is supported
template <class Archive, class CharT, class Traits>
typename std::enable_if<traits::is_output_serializable<BinaryData<CharT>, Archive>::value, void>::type
CEREAL_SAVE_FUNCTION_NAME(Archive& ar, std::basic_string_view<CharT, Traits> const& str)
{
// Save number of chars + the data
ar(make_size_tag(static_cast<size_type>(str.size())));
ar(binary_data(str.data(), str.size() * sizeof(CharT)));
}
//! Deserialization into std::basic_string_view is forbidden due to its properties as a view.
//! However std::basic_string_view can be deserialized …
Run Code Online (Sandbox Code Playgroud) c++ ×10
cereal ×10
boost ×2
json ×2
templates ×2
c++11 ×1
c++17 ×1
clion ×1
cmake ×1
copy ×1
inheritance ×1
polymorphism ×1
shared-ptr ×1
stl ×1