libuv 在 linux 上边运用相比较简单,libuv 在 linux 上边运用相比简单

引言 – 一时心起, libuv linux 搭建

895959.com,引言 – 一时心起, libuv linux 搭建

  有一天突然想起来想写个动画. 找了一晃 ui 库太大. 前边想起往日弄过的
libuv. 但发现 libuv 相关资料也很少.

  有一天突然想起来想写个动画. 找了弹指间 ui 库太大. 后边想起以前弄过的
libuv. 但意识 libuv 相关资料也很少.

由此就有了那么些内容. 

故而就有了这个内容. 

  libuv
https://github.com/libuv/libuv

  libuv
https://github.com/libuv/libuv

libuv 在 linux 上边运用相比较简单,  一从头 从 linux hello 跑起来

libuv 在 linux 下边使用相比简单,  一始发 从 linux hello 跑起来

libuv linux 安装

libuv linux 安装

先是假定你和自我同样用的是Ubuntu去做开发. 在云平台上面测试过, Ubuntu
Server 版本比 CentOS 版本少个十几兆.

首先假定你和自身一样用的是Ubuntu去做开发. 在云平台下面测试过, Ubuntu
Server 版本比 CentOS 版本少个十几兆.

有趣味朋友可以详细相比数据, 也足以品尝跑跑 Ubuntu Server .

有趣味朋友可以详细相比数据, 也得以品尝跑跑 Ubuntu Server .

# libuv 安装
cd
wget https://github.com/libuv/libuv/archive/v1.18.0.tar.gz
tar -zxvf v1.18.0.tar.gz
cd libuv-1.18.0

sh autogen.sh
./configure

make -j4

sudo make install
sudo ldconfig
cd ../
rm -rf libuv-1.18.0 v1.18.0.tar.gz
```
# libuv 安装
cd
wget https://github.com/libuv/libuv/archive/v1.18.0.tar.gz
tar -zxvf v1.18.0.tar.gz
cd libuv-1.18.0

sh autogen.sh
./configure

make -j4

sudo make install
sudo ldconfig
cd ../
rm -rf libuv-1.18.0 v1.18.0.tar.gz
```

推行上边命令操作, 我们的连串中就曾经有了 libuv 开发环境.

施行下边命令操作, 大家的系统中就曾经有了 libuv 开发环境.

有几许需要注意的是当我们要利用 libuv时候推荐用静态库.

有好几急需专注的是当我们要动用 libuv时候推荐用静态库.

gcc -l:libuv.a
gcc -l:libuv.a

到这里 linux 安装 libuv 已经完工了. 

到这里 linux 安装 libuv 已经完工了. 

  不妨写个 hello world demo

  不妨写个 hello world demo

#include <uv.h>
#include <assext.h>

//
// 测试 libuv tty 操作控制台
// 输出一段有颜色的文字
//
void uv_tty_test(void) {
    uv_tty_t tty;
    uv_buf_t buf[3];
    unsigned i, len = sizeof buf / sizeof *buf;
    uv_loop_t * loop = uv_default_loop();

    // 目前只对 tty 控制台处理
    if (uv_guess_handle(1) != UV_TTY) {
        fprintf(stderr, "uv_guess_handle(1) != UV_TTY!\n");
        exit(EXIT_FAILURE);
    }

    uv_tty_init(loop, &tty, 1, 0);
    uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL);

    // 开始发送消息
    buf[0].base = "\033[46;37m";
    buf[1].base = u8"(✿◡‿◡) 喵酱 ((●'-'●)) 比 ♥ 里~ \n";
    buf[2].base = "\033[0m";
    for (i = 0; i < len; ++i)
        buf[i].len = (int)strlen(buf[i].base);
    uv_try_write((uv_stream_t *)&tty, buf, len);

    // 重置终端行为
    uv_tty_reset_mode();
    uv_run(loop, UV_RUN_DEFAULT);
}
#include <uv.h>
#include <assext.h>

//
// 测试 libuv tty 操作控制台
// 输出一段有颜色的文字
//
void uv_tty_test(void) {
    uv_tty_t tty;
    uv_buf_t buf[3];
    unsigned i, len = sizeof buf / sizeof *buf;
    uv_loop_t * loop = uv_default_loop();

    // 目前只对 tty 控制台处理
    if (uv_guess_handle(1) != UV_TTY) {
        fprintf(stderr, "uv_guess_handle(1) != UV_TTY!\n");
        exit(EXIT_FAILURE);
    }

    uv_tty_init(loop, &tty, 1, 0);
    uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL);

    // 开始发送消息
    buf[0].base = "\033[46;37m";
    buf[1].base = u8"(✿◡‿◡) 喵酱 ((●'-'●)) 比 ♥ 里~ \n";
    buf[2].base = "\033[0m";
    for (i = 0; i < len; ++i)
        buf[i].len = (int)strlen(buf[i].base);
    uv_try_write((uv_stream_t *)&tty, buf, len);

    // 重置终端行为
    uv_tty_reset_mode();
    uv_run(loop, UV_RUN_DEFAULT);
}

代码运行效果是, 输出一段话, 并且设置背景观.  对于  uv_tty_test
可以知晓为 main (本质是 structc 一种单元测试函数约束写法)

代码运行效果是, 输出一段话, 并且设置背景象.  对于  uv_tty_test
可以精通为 main (本质是 structc 一种单元测试函数约束写法)

到这容我安利一个小东西, 感兴趣的可以品尝一下, 从零开首搭建一个 c 的
struct 小框架. 五脏逐步全了.

到这容我安利一个小东西, 感兴趣的可以尝尝一下, 从零开端搭建一个 c 的
struct 小框架. 五脏逐渐全了.

  structc
https://github.com/wangzhione/structc

  structc
https://github.com/wangzhione/structc

简单说一下libuv中应用的多少个函数,  第一个是 uv_try_write
尝试立刻发送新闻数组. 不像 uv_write 写入到信息队列中.

总而言之说一下libuv中应用的多少个函数,  第一个是 uv_try_write
尝试立时发送音信数组. 不像 uv_write 写入到音讯队列中.

int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs)

    Same as uv_write(), but won’t queue a write request if it can’t be completed immediately.
    Will return either:
        > 0: number of bytes written (can be less than the supplied buffer size).
        < 0: negative error code (UV_EAGAIN is returned if no data can be sent immediately).
int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs)

    Same as uv_write(), but won’t queue a write request if it can’t be completed immediately.
    Will return either:
        > 0: number of bytes written (can be less than the supplied buffer size).
        < 0: negative error code (UV_EAGAIN is returned if no data can be sent immediately).

当下大家是用 tty 输出到屏幕方面, 可以用那么些 api . 假如只是是走 TCP,
不要过分看重这个 api.

现阶段我们是用 tty 输出到屏幕方面, 可以用这多少个 api . 如若单独是走 TCP,
不要过于依赖这些 api.

概括为了稳定仍旧别用 uv_try_write.

简简单单为了稳定仍旧别用 uv_try_write.

第二个要说的是 uv_run

其次个要说的是 uv_run

int uv_run(uv_loop_t* loop, uv_run_mode mode)

    This function runs the event loop. It will act differently depending on the specified mode:
        UV_RUN_DEFAULT: Runs the event loop until there are no more active and referenced handles or requests. 
              Returns non-zero if uv_stop() was called and there are still active handles or requests.
               Returns zero in all other cases.
        UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if there are no pending callbacks. 
             Returns zero when done (no active handles or requests left), 
             or non-zero if more callbacks are expected 
             (meaning you should run the event loop again sometime in the future).
        UV_RUN_NOWAIT: Poll for i/o once but don’t block if there are no pending callbacks. 
              Returns zero if done (no active handles or requests left), 
              or non-zero if more callbacks are expected 
              (meaning you should run the event loop again sometime in the future).
int uv_run(uv_loop_t* loop, uv_run_mode mode)

    This function runs the event loop. It will act differently depending on the specified mode:
        UV_RUN_DEFAULT: Runs the event loop until there are no more active and referenced handles or requests. 
              Returns non-zero if uv_stop() was called and there are still active handles or requests.
               Returns zero in all other cases.
        UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if there are no pending callbacks. 
             Returns zero when done (no active handles or requests left), 
             or non-zero if more callbacks are expected 
             (meaning you should run the event loop again sometime in the future).
        UV_RUN_NOWAIT: Poll for i/o once but don’t block if there are no pending callbacks. 
              Returns zero if done (no active handles or requests left), 
              or non-zero if more callbacks are expected 
              (meaning you should run the event loop again sometime in the future).

其中 UV_RUN_DEFAULT 表示 uv_run
会一向不通运行, 只到没有工作要拍卖的时候, 才会有重返值.

其中 UV_RUN_DEFAULT 表示 uv_run
会平昔不通运行, 只到没有事情要拍卖的时候, 才会有再次回到值.

而 UV_RUN_ONCE 表示执行 poll 几遍.
类比你写代码只调用一回 select 阻塞, 直到事件激活或者逾期触发.

而 UV_RUN_ONCE 表示执行 poll 两遍.
类比你写代码只调用三次 select 阻塞, 直到事件激活或者逾期触发.

相似的 UV_RUN_NOWAIT 也是只 poll
轮询一回, 不过没有要处理事情是不会阻塞.

相似的 UV_RUN_NOWAIT 也是只 poll
轮询两回, 不过没有要拍卖事务是不会阻塞.

  到这里, 差不多 linux libuv 的 hello world 应该也算起来了.

  到此地, 差不多 linux libuv 的 hello world 应该也算起来了.

 

 

前言 – winds 跑起 libuv

前言 – winds 跑起 libuv

   下面开头带我们, 在 winds 编译最新版本 libuv.  同样在 github 上 下载
libuv 最新的宣布版本.

   下边先导带我们, 在 winds 编译最新版本 libuv.  同样在 github 上 下载
libuv 最新的发布版本.

    libuv-1.18.0

    libuv-1.18.0

解压操作完成后, 会是下面这样的

解压操作完成后, 会是下边这样的

895959.com 1

895959.com 2

这时候候先参照一下官网的 libuv 首页 README.md 表达.  

此刻候先参照一下官网的 libuv 首页 README.md 表达.  

先安装 Python 2.7 . 扯一点.  近期 python 好虎 (二〇一七年1十二月23日), 
可是依旧不知情为啥 2.7 和 3.x 版本不兼容. 

先安装 Python 2.7 . 扯一点.  最近 python 好虎 (二〇一七年1六月23日), 
可是仍然不知晓为何 2.7 和 3.x 版本不兼容. 

就当前而言依然多用 Python 2.7 感觉.  随后安装 gyp google
推出的跨平台编译环境.

就如今而言仍然多用 Python 2.7 感觉.  随后安装 gyp google
推出的跨平台编译环境.

  gyp
– https://github.com/svn2github/gyp

  gyp
– https://github.com/svn2github/gyp

由于使用的是 VS2017, 原始版本 gyp 不辅助, 请参照我提的这么些提交,
举行修改让其协助 VS2017 版本

鉴于应用的是 VS2017, 原始版本 gyp 不协理, 请参照我提的这几个提交,
举行改动让其帮助 VS2017 版本

  gyp-vs2017
version
 
– https://github.com/svn2github/gyp/pull/1/commits/66e69a51f4393bc03cc3bfec53c7c35d974339b6

  gyp-vs2017
version
 
– https://github.com/svn2github/gyp/pull/1/commits/66e69a51f4393bc03cc3bfec53c7c35d974339b6

ok winds 10 + VS2017 + libuv-1.18.0 + python2.7 + gyp + gyp vs2017
version 编译环境搭建完毕.

ok winds 10 + VS2017 + libuv-1.18.0 + python2.7 + gyp + gyp vs2017
version 编译环境搭建完毕.

初步走起, 先进入 gyp 目录执行 

开首走起, 先进入 gyp 目录执行 

python .\setup.py install
python .\setup.py install

895959.com 3

895959.com 4

形成后, 起初构建 uv.sln 工程. 先进入 libuv-1.18.0 伊始目录,
执行下边命令 

完成后, 起初构建 uv.sln 工程. 先进入 libuv-1.18.0 开端目录,
执行上边命令 

 .\vcbuild.bat release vs2017 x64 static
 .\vcbuild.bat release vs2017 x64 static

继而可以看见 uv.sln 和 Release\lib\libuv.lib 生成文件. 编译过程中
x64本子警告不少.  你一点一滴可以尝试解决,

随之可以瞥见 uv.sln 和 Release\lib\libuv.lib 生成文件. 编译过程中
x64版本警告不少.  你完全可以尝尝解决,

根本是 linux 和 winds 对于 POSIX socket writev
批量读写实现的社团用了不平等类型导致的. 

重在是 linux 和 winds 对于 POSIX socket writev
批量读写实现的构造用了不雷同类型导致的. 

友善改了它有些源码和测试代码, 消除了全方位警告. 详细 libuv 在 VS2017
下边运用无外乎 include + lib 

自己改了它有些源码和测试代码, 消除了全部警告. 详细 libuv 在 VS2017
上边运用无外乎 include + lib 

带上 libuv.h 下面的 include 头文件

带上 libuv.h 下面的 include 头文件

 895959.com 5 

 895959.com 6 

再增长项目工程中导入下边库 

再添加项目工程中导入下边库 

advapi32.lib
iphlpapi.lib
psapi.lib
shell32.lib
user32.lib
userenv.lib
ws2_32.lib
advapi32.lib
iphlpapi.lib
psapi.lib
shell32.lib
user32.lib
userenv.lib
ws2_32.lib

头文件什么的简短导入上面就足以了 

头文件什么的简便导入下边就足以了 

WIN32_LEAN_AND_MEAN
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_DEPRECATE
_WINSOCK_DEPRECATED_NO_WARNINGS
WIN32_LEAN_AND_MEAN
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_DEPRECATE
_WINSOCK_DEPRECATED_NO_WARNINGS

到这差不多 libuv winds 就大功告成了.  

到这差不多 libuv winds 就大功告成了.  

这边写了个示范 demo, 有趣味的可以品尝训练一下

此处写了个示范 demo, 有趣味的能够尝尝磨练一下

#include <uv.h>
#include <assext.h>

// 继承 uv_timer_t 结构
struct gravity {
    uv_timer_t tick;

    uv_tty_t tty;

    int width;
    int height;
    int pos;

    char * msg;
};

// _update - 更新图片内容
static void _update(struct gravity * grav) {
    char data[BUFSIZ];
    uv_buf_t buf;
    buf.base = data;
    //
    // \033[2J      : 清屏
    // \033[H       : 光标移到(0, 0)
    // \033[%dB     : 光标下移 %d 行
    // \033[%dC     : 光标右移 %d 行
    // \033[42;37m  : 底色 41 绿底, 字色 37 白字
    //
    // \033[0m      : 关闭所有属性
    //
    buf.len = sprintf(data, "\033[2J\033[H\033[%dB\033[%dC\033[42;37m%s",
                            grav->pos,
                            (grav->width - (int)strlen(grav->msg)) / 2,
                            grav->msg);
    assert(buf.len < BUFSIZ);
    if (grav->pos == grav->height) {
        // 关闭屏幕额外属性
        const char * resets = "\033[0m";
        strcat(data, resets);
        buf.len += (int)strlen(resets);
    }

    // 写入消息
    uv_try_write((uv_stream_t *)&grav->tty, &buf, 1);

    // 当超过当前屏幕, 退出定时器
    if (++grav->pos > grav->height) {
        // 重置tty
        uv_tty_reset_mode();
        uv_timer_stop(&grav->tick);
    }
}

//
// uv_timer_test - 测试 timer 使用
//
void uv_timer_test(void) {
    uv_loop_t * loop = uv_default_loop();
    struct gravity grav = { { 0 } };

    uv_tty_init(loop, &grav.tty, 1, 0);
    uv_tty_set_mode(&grav.tty, UV_TTY_MODE_NORMAL);

    // 获取当前屏幕宽高信息
    if (uv_tty_get_winsize(&grav.tty, &grav.width, &grav.height)) {
        fprintf(stderr, "Could not get TTY information\n");
        uv_tty_reset_mode();
        return;
    }

    fprintf(stderr, "Width %d, height %d\n", grav.width, grav.height);

    // 启动 timer 刷新屏幕信息
    grav.msg = u8"我不甘心 ~";
    uv_timer_init(loop, &grav.tick);
    uv_timer_start(&grav.tick, (uv_timer_cb)_update, 200, 200);

    uv_run(loop, UV_RUN_DEFAULT);
}
#include <uv.h>
#include <assext.h>

// 继承 uv_timer_t 结构
struct gravity {
    uv_timer_t tick;

    uv_tty_t tty;

    int width;
    int height;
    int pos;

    char * msg;
};

// _update - 更新图片内容
static void _update(struct gravity * grav) {
    char data[BUFSIZ];
    uv_buf_t buf;
    buf.base = data;
    //
    // \033[2J      : 清屏
    // \033[H       : 光标移到(0, 0)
    // \033[%dB     : 光标下移 %d 行
    // \033[%dC     : 光标右移 %d 行
    // \033[42;37m  : 底色 41 绿底, 字色 37 白字
    //
    // \033[0m      : 关闭所有属性
    //
    buf.len = sprintf(data, "\033[2J\033[H\033[%dB\033[%dC\033[42;37m%s",
                            grav->pos,
                            (grav->width - (int)strlen(grav->msg)) / 2,
                            grav->msg);
    assert(buf.len < BUFSIZ);
    if (grav->pos == grav->height) {
        // 关闭屏幕额外属性
        const char * resets = "\033[0m";
        strcat(data, resets);
        buf.len += (int)strlen(resets);
    }

    // 写入消息
    uv_try_write((uv_stream_t *)&grav->tty, &buf, 1);

    // 当超过当前屏幕, 退出定时器
    if (++grav->pos > grav->height) {
        // 重置tty
        uv_tty_reset_mode();
        uv_timer_stop(&grav->tick);
    }
}

//
// uv_timer_test - 测试 timer 使用
//
void uv_timer_test(void) {
    uv_loop_t * loop = uv_default_loop();
    struct gravity grav = { { 0 } };

    uv_tty_init(loop, &grav.tty, 1, 0);
    uv_tty_set_mode(&grav.tty, UV_TTY_MODE_NORMAL);

    // 获取当前屏幕宽高信息
    if (uv_tty_get_winsize(&grav.tty, &grav.width, &grav.height)) {
        fprintf(stderr, "Could not get TTY information\n");
        uv_tty_reset_mode();
        return;
    }

    fprintf(stderr, "Width %d, height %d\n", grav.width, grav.height);

    // 启动 timer 刷新屏幕信息
    grav.msg = u8"我不甘心 ~";
    uv_timer_init(loop, &grav.tick);
    uv_timer_start(&grav.tick, (uv_timer_cb)_update, 200, 200);

    uv_run(loop, UV_RUN_DEFAULT);
}

其一屏幕音信会动 哈哈, : )

以此屏幕新闻会动 哈哈, : )

895959.com 7 

895959.com 8 

(二傻子 入场 ~ ) 

(二傻子 入场 ~ ) 

 

 

正文 – 稍加训练

正文 – 稍加磨练

  通过以上对libuv环境的搭建和简单先入为主的概念性描述,.
此时通通可以动用 libuv tty 简单做个

  通过以上对libuv环境的搭建和精炼先入为主的概念性描述,.
此时统统可以利用 libuv tty 简单做个

跨平台的小动画了.  我先写个, 推荐我们参考例子抄写一回, 作育手感.
扯一点互联网技术有五个样子

跨平台的小动画了.  我先写个, 推荐我们参考例子抄写一回, 培育手感.
扯一点互联网技术有六个方向

架构师和技艺专家. 有点像往日游戏支付中服务器架设和客户端引擎.
不过C程序员依然强调手感,

架构师和技巧专家. 有点像往日游戏开发中服务器架设和客户端引擎.
不过C程序员依旧强调手感,

弱化架构, 追求极致的统一.  (说白点, 代码更紧要, 能说更好.)

弱化架构, 追求极致的统一.  (说白点, 代码更要紧, 能说更好.)

#include <uv.h>
#include <chead.h>
#include <assext.h>

struct love {
    uv_timer_t tick;

    uv_tty_t tty;

    int width;
    int height;
    int pos;

    char ** msgs;
    int len;
};

static char * _figure[] = {
    u8"  背影 :- 汪国真\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很简单\n",
    u8"  简单\n",
    u8"  是一种风景\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很年轻\n",
    u8"  年轻\n",
    u8"  是一种清明\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很含蓄\n",
    u8"  含蓄\n",
    u8"  是一种魅力\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很孤零\n",
    u8"  孤零\n",
    u8"  更让人记得清\n"
};

// _love_stty : 内部发送消息
static inline void _love_stty(struct love * love, const char * msg) {
    uv_buf_t buf;
    buf.base = (char *)msg;
    buf.len = (int)strlen(buf.base);
    uv_try_write((uv_stream_t *)&love->tty, &buf, 1);
}

// _love_init : 初始化当前 tty 结构
static void _love_init(struct love * love) {
    uv_loop_t * loop = uv_default_loop();
    memset(love, 0, sizeof *love);

    // 初始化 tty 环境
    uv_tty_init(loop, &love->tty, 1, 0);
    uv_tty_set_mode(&love->tty, UV_TTY_MODE_NORMAL);

    // 只对 tty 输出处理
    if (uv_guess_handle(1) != UV_TTY)
        CERR_EXIT("uv_guess_handle(1) != UV_TTY!");

    // 获取当前屏幕宽高信息
    if (uv_tty_get_winsize(&love->tty, &love->width, &love->height)) {
        uv_tty_reset_mode();
        CERR_EXIT("Could not get TTY information");
    }

    // 设置具体内容
    love->msgs = _figure;
    love->len = LEN(_figure);

    // 初始化定时器
    uv_timer_init(loop, &love->tick);
}

// _love_screem : 屏幕绘制内容
static void _love_screem(struct love * love) {
    char buf[BUFSIZ];
    int cnt = love->pos < love->len ? love->pos : love->len;

    // 重置索引位置
    int idx = love->height - love->pos;
    snprintf(buf, LEN(buf), "\033[2J\033[H\033[%dB", idx);
    _love_stty(love, buf);

    // 全部显示
    for (idx = 0; idx < cnt; idx++)
        _love_stty(love, love->msgs[idx]);
}

// _update - 更新刷新事件
static void _love_update(struct love * love) {
    ++love->pos;

    // 开始绘制内容
    _love_screem(love);

    // 运行结束直接返回
    if (love->pos >= love->height) {
        // 重置tty
        uv_tty_reset_mode();
        uv_timer_stop(&love->tick);
    }
}

//
// uv_love_test - 情怀 ~
//
void uv_love_test(void) {
    struct love love;
    _love_init(&love);

    // 开始初始化, 定时器刷新事件
    uv_timer_start(&love.tick, (uv_timer_cb)_love_update, 200, 200);

    // 事件启动起来
    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}
#include <uv.h>
#include <chead.h>
#include <assext.h>

struct love {
    uv_timer_t tick;

    uv_tty_t tty;

    int width;
    int height;
    int pos;

    char ** msgs;
    int len;
};

static char * _figure[] = {
    u8"  背影 :- 汪国真\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很简单\n",
    u8"  简单\n",
    u8"  是一种风景\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很年轻\n",
    u8"  年轻\n",
    u8"  是一种清明\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很含蓄\n",
    u8"  含蓄\n",
    u8"  是一种魅力\n",
    u8"  \n",
    u8"  背影\n",
    u8"  总是很孤零\n",
    u8"  孤零\n",
    u8"  更让人记得清\n"
};

// _love_stty : 内部发送消息
static inline void _love_stty(struct love * love, const char * msg) {
    uv_buf_t buf;
    buf.base = (char *)msg;
    buf.len = (int)strlen(buf.base);
    uv_try_write((uv_stream_t *)&love->tty, &buf, 1);
}

// _love_init : 初始化当前 tty 结构
static void _love_init(struct love * love) {
    uv_loop_t * loop = uv_default_loop();
    memset(love, 0, sizeof *love);

    // 初始化 tty 环境
    uv_tty_init(loop, &love->tty, 1, 0);
    uv_tty_set_mode(&love->tty, UV_TTY_MODE_NORMAL);

    // 只对 tty 输出处理
    if (uv_guess_handle(1) != UV_TTY)
        CERR_EXIT("uv_guess_handle(1) != UV_TTY!");

    // 获取当前屏幕宽高信息
    if (uv_tty_get_winsize(&love->tty, &love->width, &love->height)) {
        uv_tty_reset_mode();
        CERR_EXIT("Could not get TTY information");
    }

    // 设置具体内容
    love->msgs = _figure;
    love->len = LEN(_figure);

    // 初始化定时器
    uv_timer_init(loop, &love->tick);
}

// _love_screem : 屏幕绘制内容
static void _love_screem(struct love * love) {
    char buf[BUFSIZ];
    int cnt = love->pos < love->len ? love->pos : love->len;

    // 重置索引位置
    int idx = love->height - love->pos;
    snprintf(buf, LEN(buf), "\033[2J\033[H\033[%dB", idx);
    _love_stty(love, buf);

    // 全部显示
    for (idx = 0; idx < cnt; idx++)
        _love_stty(love, love->msgs[idx]);
}

// _update - 更新刷新事件
static void _love_update(struct love * love) {
    ++love->pos;

    // 开始绘制内容
    _love_screem(love);

    // 运行结束直接返回
    if (love->pos >= love->height) {
        // 重置tty
        uv_tty_reset_mode();
        uv_timer_stop(&love->tick);
    }
}

//
// uv_love_test - 情怀 ~
//
void uv_love_test(void) {
    struct love love;
    _love_init(&love);

    // 开始初始化, 定时器刷新事件
    uv_timer_start(&love.tick, (uv_timer_cb)_love_update, 200, 200);

    // 事件启动起来
    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}

职能是从上到下输出了汪国真先生诗词背影~ 🙂 

效率是从上到下输出了汪国真先生诗词背影~ 🙂 

  背影
https://pan.baidu.com/s/1kVd5aRX

  背影
https://pan.baidu.com/s/1kVd5aRX

      背景,  总是很简短, 更令人记得清 

      背景,  总是很简单, 更让人记得清 

895959.com 9

895959.com 10

 

 

后记 – 好久没扯淡了

后记 – 好久没扯淡了

  有问题欢迎交换, 错误是难免的, 发现再改吧 ~  O_O

  有题目欢迎互换, 错误是难免的, 发现再改吧 ~  O_O

  只为你活一天
– http://music.163.com/m/song?id=29999535&userid=16529894

  只为你活一天
– http://music.163.com/m/song?id=29999535&userid=16529894