diff --git a/README.md b/README.md index 42e2eff..1a8d57a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Messenger SDK 开发文档 -感谢您的访问. +感谢你的访问. 本站旨在为Messenger开发者提供清晰的入门资料. ## 版权声明 @@ -25,10 +25,10 @@ SDK使用C++编写,使用Messenger SDK需要一定的C++基础。 ## 免责声明 -本文档仅仅用来指导您如何使用Messenger SDK,我们对您使用Messenger SDK进行的一切行为不承担任何责任, -由此导致的一切后果由您自行承担。 +本文档仅仅用来指导你如何使用Messenger SDK,我们对你使用Messenger SDK进行的一切行为不承担任何责任, +由此导致的一切后果由你自行承担。 如果您不能认可以上内容,请立即**关闭此文档**。 -当您打开本章节之后的内容,我们视为你已经认可了我们的免责声明。 +当你打开本章节之后的内容,我们视为你已经认可了我们的免责声明。 diff --git a/doc/entry.md b/doc/entry.md index 613e177..f352d46 100644 --- a/doc/entry.md +++ b/doc/entry.md @@ -12,8 +12,8 @@ Messenger SDK一般是一个如下格式的压缩包 ... -其中,libs下放置的是一些静态连接库,包含Android、Linux以及Windows。你需要将这些静态链接库链接到您的项目中, -并且在您项目的头文件搜索路径中添加 *include* 文件夹。 +其中,libs下放置的是一些静态连接库,包含Android、Linux以及Windows。你需要将这些静态链接库链接到你的项目中, +并且在你项目的头文件搜索路径中添加 *include* 文件夹。 然后,你将可以使用Messenger的API了。 @@ -25,7 +25,7 @@ Messenger SDK的主要class是 ling::Messenger ,它提供了服务器全部API > ling::Messenger以及ling::Client,都具有ling前缀,在C++中,这叫命名空间(*namespace*)。SDK内全部的class都在ling命名空间下。 -ling::Messenger将是您接触最多的class。 +ling::Messenger将是你接触最多的class。 它有两个构造函数: ~~~cpp @@ -91,3 +91,112 @@ int main(void){ ~~~ +得到**ling::Messenger**的实例之后,你可以通过它来调用Messenger的API。 +例如,像这样来向服务器内注册当前设备。 + +~~~ cpp + +#include + +std::shared_ptr api = ... + +std::filesystem::path filePath = "/path/to/your/flag"; +try{ + if (!std::filesystem::exists(filePath)) { + ::api->createDevice([](std::shared_ptr data)->void{ + //此处的代码将会在服务器响应createDevice时被执行 + if(data->isSuccess()){ + //注册设备成功,则在磁盘上留下一个标记,下次启动时不再注册 + std::ofstream outputFile(filePath); + outputFile.close(); + //然后,可以调用其他api了。 + } else { + //服务器拒绝注册请求,可能是因为一些异常问题导致的,一般不会出现。 + //为了程序健壮性,此处需要记录日志,这里仅仅打印一下。 + std::cout << data->getMessage() << std::endl; + } + }); + } +} catch (const ling::SendException & e){ + //所有需要和服务器交换数据的api都会在网络断开时抛出此异常 + //具体信息请查看异常处理一节。 + //有无需捕获异常的优雅方法,将在后续章节中介绍。 +} + +~~~ + +### 发生了什么? + +上面的代码可以简化成如下这样 + +~~~ cpp + +::api->createDevice([](std::shared_ptr data)->void{ + +}); + +~~~ + +简单来说,就是调用了全局命名空间中api对象的createDevice成员方法,并将一个lambda表达式作为参数传递给了它。 + +lambda,即匿名函数(*Anonymous Function*)。 + +查看createDevice方法的定义 + +~~~ cpp +void createDevice(const std::function)> &call); +~~~ + +可以看到它需要一个**std::function**类型的参数。**std::function**是C++可调用对象的包装,它可以是一个具名函数 +,一个lambda表达式,也可以是一个class的成员方法,一个仿函数等等。一切可调用对象都可以使用**std::function**来包装。 + +参数中紧跟在**std::function**后面的 **>)>** 是这个**std::function**的模板参数, +表示此**std::function**包装的可调用对象没有返回值,并且只需要一个 **std::shared_ptr** 类型的参数。 + +前面已经介绍过**std::shared_ptr**了,它同样是一个模板类型,尖括号中的**ServerDataSuper**是此智能指针管理对象的指针。 + +**ServerDataSuper**是Messenger服务器响应数据的封装类型,是所有响应数据的基类。换句话说 +,所有包装服务器响应数据的类型,都**直接或间接**的派生自**ServerDataSuper**。 + +例如,如下是服务器对登陆账号请求的响应信息包装类型的声明 + +~~~ cpp + +namespace ling { + class LoginUserData : public ServerDataSuper { + }; +} +~~~ + +可以看到它直接从ServerDataSuper派生,这意味着你可以在任何服务器响应类型中调用ServerDataSuper中的方法,它们是公共的。 + +对ServerDataSuper的介绍将在后续章节继续。 + +回到createDevice。 + +将上述简化代码继续简化,可以变成下面的样子。 + +~~~ cpp + +/// 这段代码和上面简化后的代码是等价的! + +void createDeviceResponse(std::shared_ptr data){ + //等到服务器响应后,Messenger才会调用这个函数。 + //注意,Messenger将在单独的线程中调用此函数 + //Messenger将采取一定的策略管理线程,无论如何,你都不应该在此类回调函数中执行需要消耗大量时间的操作。 +} + +::api->createDevice(createDeviceResponse); +//调用后将会立即返回,继续向下执行 + +~~~ + +createDeviceResponse的定义,**等价与**上面代码中的lambda表达式。 + +Messenger SDK的API是同服务器异步通信的,也就是说createDevice会立即返回,并继续向下执行。 +等服务器响应createDevice时,Messenger SDK将会调用参数中传递进去的可调用对象 +(在这里是createDeviceResponse)并构造ServerDataSuper对象作为参数。 + +> 这都是C++的基础语法。请百度 回调函数(*callback*) + + diff --git a/index.html b/index.html index 3d92919..4a1394f 100644 --- a/index.html +++ b/index.html @@ -14,7 +14,7 @@