分类目录归档:社区开源项目

一个好用的短信发送的客户端

背景

最近需要做一个登录短信验证的功能,看了不少短信平台,对于c++接口的支持不友好,有的甚至没有,有的是通过curl去实现的,还是同步的,比较难用。于是就基于boost.asio用c++17实现了一个异步的短信发送客户端, 非常好用,只有一个发送短信的接口。
现在工程中的例子是以云片短信平台为例子的,你可以很容易修改为其他的短信平台。

特点

sms_client的主要特点:

  1. header only
  2. async
  3. easy to use

快速示例

一个header only的c++ 日志库

背景

NanoLog是一个非常小巧的log库,代码很少,不到一千行,速度比spdlog还快,应用上也能满足需求,我很喜欢。但是也存在一些不足,比如日志文件的数量没有限制,每次重启之后会从头开始写等等问题,还需要进一步完善。于是我新建了一个工程nanolog,这个工程继承于nanolog,将原工程改成header only,并用了一些最新的特性来简化原来的代码。

快速示例

如何编译

由于使用了C++17的新特性,所以需要支持C++17的编译器,gcc7.2,vs2017 15.5

roadmap

  1. 增加文件数量上限
  2. 重新写日志从上次的位置继续写

C++17实现的一个简单的redis客户端

motiviation

实现最常用的redis操作,只支持数字类型字符串类型(包括std::string, c字符串,和字符串数组),简单好用。

基本接口

有这三个接口后用户就可以很方便地使用redis了。

注意:get接口会抛异常,当字符串转换为对应的值失败时会抛异常,当要取的k-v不存在时也会抛异常。

基本用法

roadmap

  1. 增加conneciton pool
  2. 增加更多redis访问接口

ormpp使用文档

目录

ormpp的目标

ormpp最重要的目标就是让c++中的数据库编程变得简单,为用户提供统一的接口,支持多种数据库,降低用户使用数据库的难度。

ormpp的特点

ormpp是modern c++(c++11/14/17)开发的ORM库,目前支持了三种数据库:mysql, postgresql和sqlite,ormpp主要有以下几个特点:

  1. header only
  2. cross platform
  3. unified interface
  4. easy to use
  5. easy to change database

你通过ormpp可以很容易地实现数据库的各种操作了,大部情况下甚至都不需要写sql语句。ormpp是基于编译期反射的,会帮你实现自动化的实体映射,你再也不用写对象到数据表相互赋值的繁琐易出错的代码了,更酷的是你可以很方便地切换数据库,如果需要从mysql切换到postgresql或sqlite只需要修改一下数据库类型就可以了,无需修改其他代码。

快速示例

这个例子展示如何使用ormpp实现数据库的增删改查之类的操作,无需写sql语句。

如何编译

编译器支持

需要支持C++17的编译器, 要求的编译器版本:linux gcc7.2, clang4.0; windows >vs2017 update5

数据库的安装

因为ormpp支持mysql, postgresql和sqlite,所以需要安装mysql,postgresql,postgresql官方提供的libpq以及sqlite3,安装之后,在CMakeLists.txt配置目录和库路径。

上面两步完成之后就可以直接编译了。

接口介绍

ormpp屏蔽了不同数据库操作接口的差异,提供了统一简单的数据库操作接口,具体提供了数据库连接、断开连接、创建数据表、插入数据、更新数据、删除数据、查询数据和事务相关的接口。

接口概览

具体的接口使用介绍

先在entity.hpp中定义业务实体(和数据库的表对应),接着定义数据库对象:

  1. 连接数据库

返回值:bool,成功返回true,失败返回false.

  1. 断开数据库连接

注意:用户可以不用显式调用,在数据库对象析构时会自动调用disconnect接口。

返回值:bool,成功返回true,失败返回false.

3.创建数据表

create_datatable example:

注意:目前只支持了key和not null属性,并且只支持单键,还不支持组合键,将在下一个版本中支持组合键。

返回值:bool,成功返回true,失败返回false.

4.插入单条数据

返回值:int,成功返回插入数据的条数1,失败返回INT_MIN.

5.插入多条数据

返回值:int,成功返回插入数据的条数N,失败返回INT_MIN.

  1. 更新单条数据

注意:更新会根据表的key字段去更新,如果表没有key字段的时候,需要指定一个更新依据字段名,比如

[/crayon]

返回值:int,成功返回更新数据的条数1,失败返回INT_MIN.

5.插入多条数据

注意:更新会根据表的key字段去更新,如果表没有key字段的时候,需要指定一个更新依据字段名,用法同上。

返回值:int,成功返回更新数据的条数N,失败返回INT_MIN.

  1. 删除数据

返回值:bool,成功返回true,失败返回false.

7.单表查询

返回值:std::vector,成功vector不为空,失败则为空.

8.多表或特定列查询

返回值:std::vector<std::tuple>,成功vector不为空,失败则为空.

9.执行原生sql语句

注意:execute接口支持的原生sql语句是不带占位符的,是一条完整的sql语句。

返回值:int,成功返回更新数据的条数1,失败返回INT_MIN.

10.事务接口

开始事务,提交事务,回滚

返回值:bool,成功返回true,失败返回false.

11.面向切面编程AOP

定义切面:
struct log{
//args…是业务逻辑函数的入参
template<typename… Args>
bool before(Args… args){
std::cout<<“log before”<<std::endl;
return true;
}

[/crayon]

注意:切面的定义中,允许你只定义before或after,或者二者都定义。

roadmap

  1. 支持组合键。
  2. 多表查询时增加一些诸如where, group, oder by, join, limit等常用的谓词,避免直接写sql语句。
  3. 增加日志
  4. 增加获取错误消息的接口
  5. 支持更多的数据库

联系方式

purecpp@163.com

http://purecpp.org/

https://github.com/qicosmos/ormpp

ormpp–一个很酷的Modern C++ ORM库

ormpp是modern c++(c++11/14/17)开发的ORM库,为数据库操作提供了统一、灵活和易用的接口,目前支持了三种数据库:mysql, postgresql和sqlite。ormpp主要有以下几个特点:

  1. header only
  2. cross platform
  3. unified interface
  4. easy to use
  5. easy to change database

你很容易就可以实现数据库的各种操作了,大部情况下甚至都不需要写sql语句了。ormpp是基于编译期反射的,会帮你实现自动化的实体映射,你再也不用写对象到数据表相互赋值的繁琐易出错的代码了,更酷的是你可以很方便地切换数据库,如果需要从mysql切换到postgresql或sqlite只用修改一行代码就可以实现切换。

编译需要支持c++17的编译器,gcc7.2, clang4.0,vs2017 upate5+.

让我们来看看如何使用ormpp吧:

如何你想把数据库换成postgresql或sqlite,你仅仅需要将mysql类型换成postgresql或sqlite, 其他代码不需要做任何修改,非常简单。

ormpp让数据库编程变得简单,enjoin it!

iguana支持了C++17

iguana做了更新,增加了C++17的版本,之前C++14的版本并不受影响。

如何使用

如何使用C++17版本的iguana呢?很简单。

  1. 需要支持C++17的编译器:gcc7.1, clang4.0,由于vs2017只支持了很少的C++17特性,因此在vs2017上用不了C++17版本的iguana.

  2. 引用C++17版本的头文件,如include “json17.hpp”即可。

  3. CMakelists.txt中设置C++17的flag。

用到了哪些C++17的新特性?

主要用到了C++17的constexpr:constexpr if, constexpr lambda; fold expression, string_view, inline variable, nested namespace.

C++17用起来很舒服,enjoy it.

欢迎大家使用基于编译期反射的序列化引擎iguana

扩展模板库的新方法 – 善用函数的ADL查找

问题

随着C++语言的发展,越来越多的C++类库都使用模板库提供给大家使用。模板库通常使用基于对象的设计,相比传统的面向对象的设计而言,前者的每个模块可以单独使用,而不依赖框架。整个模板库的框架,只是一个胶水层,让各个组件之间按照某种协议,组合到一起,形散而神不散,发挥出强大的功能。而且模板库非常好扩展。模板库的扩展通常有以下三种模式:

  1. 函数重载;
  2. Policy Based Design, 按照框架规定好的协议导出指定的type,计算好特定的静态常量和实现特定的函数;
  3. 特化traits或者一些特定模板组件的特化;

由于前两种方式比较简单,还要就是没有找到比较好的素材,鄙文暂时主要讨论第三种扩展方式。在实现iguana的过程中,我们发现模板特化和宏的结合,在碰到命名空间的时候,我们一筹莫展。案例如下,

REFELCTION宏实质上生成了一个在全局命名空间下的类模板的特化的代码。但是由于宏是预处理阶段,生成的代码在client命名空间下。C++的语言规范不允许在一个命名空间中特化另一个命名空间的类模板,也不允许在一个命名空间下特化全局命名空间的类模板(全局的情况MSVC能编过,我是服气的)。这里是一个参考链接。

那么我们库中遇到的问题,用下列简化的代码给出,有兴趣的读者可以到各个编译环境下测试。

其实这个限制并不是无解,只要你保证REFLEACTION宏在全局命名空间下,就不会出错。例如BOOST_FUSION_ADAPT_STRUCT宏,也是用相同的方法规避的。但是你会发现这样对使用来说非常不便,你偶尔不得不把一个完整的命名空间的代码block拆成两个。我们得找另外一种方法来扩展我们的模板库,而不受限于命名空间。

解决方案

什么样的扩展方法,可以跨越命名空间的限制?仔细阅读过template C++的读者应该不难发现,就是函数的ADL查找。我们用如下代码来说明,如何利用函数的ADL查找。

简单解释一下,下面的代码是如何工作的。首先,函数的ADL查找,是apply函数尝试调用to_extend的时候,不仅会查找lib命名空间下的符号,也会去查找T类型所在命名空间的符号。我们定义的to_extend函数在client命名空间下,foo类型也在client命名空间下。那么ADL查找肯定可以找到to_extend函数的符号。然后,我们没有选择类模板的特化,而是选择了使用to_extend函数,返回一个它内部定义的类型作为policy的功能。这个思想有点类似Andrei Alexandrescu大神的MDC中第11章节的Multimethod的蹦床函数,trampoline funciton. 有了这些,我们就可以在任意命名空间下来扩展我们的模板库,当然配合宏使用也没有问题了。在iguana中具体实现的小细节,可以参考reflection.hpp里面的实现。

A Universal ORM Engine based on compile time Reflection

A Universal ORM Engine based on Reflection

ormpp is a modern, universal and easy-to-use ORM engine developed in c++14. ormpp only supports sqlite now, however ormpp can support any database, such as mysql, postgresql,oracle etc. ormpp will support many kind of database in future. ormpp is in developing now.

Motivation

Simplify database operation with compile-time reflection.ormpp provides very simple and universal interface, although the databases type are different.In short ormpp shields the difference of the bottom database.
This library provides a portable cross-platform way of:

  • operation of sqlite
  • operation of mysql(in the paln)
  • operation of postgresql(in the paln)
  • operation of any other database

Tutorial

This Tutorial is provided to give you a view of how to use ormpp, now it is only concerned with sqlite.

Data manipulation

Create a database.

Create a table.

The excecute method is a universal interface, it can accept any data manipulation sql string. So you can also call excecute for insert, update and delete etc.

Binding parameters.

The excecute interface support binding parameters, bellow is an example.

If the statement needs some later binding parameters, pass the parameters straight forward. ormpp will atomically binding theparameters.

Operation with object

If you get tired of filling many parameters, you can choose object instead. ormpp can automatically make sql with compile-time reflection.Bellow is an example of inserting with object.
Firstly, define meta data just as iguana dose.

Secondly, directly call excecute interface.

ignore some fields of an object

insert interface provides a default parameter which is used to tell ormpp which fields would be ignored.Just need pass the fields indexes.Bellow is an example about ignore specific fields:

Query table

Query table is also very simple, just need call a query interface with a reflection object.

How about multiple tables query? Still call the query interface.

If you query parts of tables, still call the query interface

Full sources:

  • https://github.com/qicosmos/ormpp/blob/master/example.cpp

If you found a bug, please create an issue on GitHub with a detailed description. If you like it please star it

A universal serialization engine based on compile time reflection

iguana is a modern, universal and easy to use serialization engine developed in c++14.

Motivation

Serialize an object to any other format data with compile time reflection, such as json, xml, binary,table and so on.
This library was degined to unify and simplify serialization in a portable cross-plateform manner. This library is also easily to extend, you can serialize any format data with the library.
Library provides a portable across platforms way to:

  • serialization of json
  • serialization of xml
  • serialization of any customized format

Tutorial

This Tutorial is provided to give you an view of how to iguana for serialization.

serialization of json

The first thing to do when you serialize an object is to define meta data. There is an example of defining meta data.

Defining meta data is very simple, just needs to difine a ‘REFLECTION’ micro.

Now let’s serialize person to json string.

This example will output:

serialize person to json string is also very simple, just need to call to_json method, there is nothing more.

How about deserialization of json? Look at the follow example.

It’s as simple as serialization, just need to call from_json method.

serialization of xml

Serialization of xml is similar with json. The first step is also defining meta data as above. This is a complete example.

a complicated example

iguana can deal with objects which contain another objects and containers. Here is the example:

At first define meta data:

Then call the simple interface:

Full sources:

  • https://github.com/qicosmos/iguana/blob/master/example.cpp

F.A.Q

  • Question: Why is the name called iguana?

    • Answer: I think serialization is like an iguana, because the change is only the display format, however the meta data is never changed. With changeless meta data and reflection you can serializa an object to any format which is like an iguana does.
  • Question: Is iguana support raw pointer?

    • Answer: No. iguana doesn’t support raw pointer, but will surpport smart pointer in the future.
  • Question: Is iguana thread safe?

    • Answer: Not yet, but it’s not a problem, you can use lock before call from_json or to_json.
  • Question: Is iguana high performance?

    • Answer: Yes it is, because iguana is based on compile time reflection.
  • Question: I have found a bug, how do I notify?
    Answer: Create an issue at GitHub with a detailed description.

If you like iguana, please star it, thanks.

Copy Protected by Chetan's WP-Copyprotect.