Project RC

一只腊鸡的技术成长。

从 DLL 文件生成 LIB 文件

创建于
分类:DevDetailed
标签:动态链接库Windows酷Q

标题可能有一定误导嫌疑,首先这里的 lib 文件不是指静态编译的 lib 文件,而是和 dll 配套使用的用来通过链接的 lib 文件;另外也不是从 dll 生成,而是直接生成,只是需要先通过 dll 来查看有哪些导出函数。

故事背景

在做酷 Q 插件开发的时候,发现官方的 C++ SDK 很久没有更新了,找了一圈发现其实它的函数实现都在安装目录的 CQP.dll,我要做的就是能让 C++ 代码去调用里面的函数,根据官方 SDK 的结构,光使用头文件来声明是没有用的,还需要一个 .lib 文件,研究了一圈发现其实 SDK 所谓的 .lib 文件并不是真正的函数实现,而只是用来通过编译的一个东西,它内部实际上是对 dll 中的函数的一些描述。于是就有了后面的折腾。

方法和坑……

需要说明的是,这里主要说的是针对酷 Q 的 dll 的情况,似乎编译 dll 的时候,函数的修饰符会影响很多结果,我也不太清楚酷 Q 具体是怎么修饰的导出函数,所以,这里说的方法可能不具有普适性。

我本来以为那个 .lib 文件是把 dll 转换成静态编译的,但似乎这其实是做不到的(或者我没找到办法),然后发现只是一个对 dll 里函数的描述,于是找到了生成 lib 文件的办法。

获取 DLL 文件的导出函数列表

首先需要知道代码里面会调用那些函数的函数名称和参数列表,这也就需要知道 dll 里面有哪些函数。打开 VS 附带的一个「Visual Studio Developer Command Prompt」(可以在开始菜单搜索到),然后进入 dll 文件所在目录,运行 dumpbin.exe /exports Some.dll > dump 即可把导出函数等一堆信息 dump 到 dump 文件中,类似下面这样:

Microsoft (R) COFF/PE Dumper Version 14.10.25019.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file .\CQP.dll

File Type: DLL

  Section contains the following exports for CQP.dll

    00000000 characteristics
    590B3029 time date stamp Thu May  4 21:44:09 2017
        0.00 version
           1 ordinal base
          36 number of functions
          36 number of names

    ordinal hint RVA      name

          1    0 0006F0D2 CQ_addLog
          2    1 0006F1D2 CQ_getAppDirectory
          3    2 0006F12C CQ_getCookies
          4    3 0006F160 CQ_getCsrfToken

......

从这里就可以知道 dll 的导出函数有哪些,不过只有函数名,我这里遇到的情况,还需要知道参数列表(准确地说是参数列表所占用的字节数)。

……

从 DLL 文件生成 LIB 文件

把博客迁移到 VeriPress 了

创建于
分类:Misc
标签:BlogVeriPress

好几天前就写好了 VeriPress 的初始版本(说初始版本是因为有一些功能在写之前就打算放在第二版来实现,不过目前看来,这个就当个 flag 好了……),一直没空把自己博客迁移过来,刚刚抽空把 VPS 全整理了一下,然后终于迁移了博客。

不得不说我之前真的蠢,竟然直接拿 Flask 的 run() 来跑,这次是用 uWSGI 和 nginx 跑的 Flask 的 app 对象,并开启了 HTTP/2 支持。

不过由于新的 VeriPress 和原来的 BlogA 在给评论框提供文章的唯一标识不一样了,原来的 Disqus 评论在新的上也就看不到了,虽然 Disqus 官方有一个迁移工具,但我想本来也没有几个评论,也就不折腾了吧,况且 Disqus 被墙了,感觉其实不是一个好的选择,就先这样吧。

再说一下我现在跑 VeriPress 的方法,首先在 VPS 用 virtualenv 来安装,VeriPress 实例放在主目录,然后通过 uWSGI 指定 virtualenv 的路径和工作目录,文章和页面在本地电脑上保存,写新文章之后用 sftp 同步到 VPS。这样整个流程基本上用起来还算舒服,缺点就是需要手动同步文章等数据,但现在实在懒得配置 GitHub 的 webhook 来自动更新了。

其实还是非常想后面有空给 VeriPress 加上数据库存储支持的,同时加上后台管理页面,这样也就不用费心同步文件了。

另外就是博客主题,由于不是很有空,就先用着之前写的默认主题了,后面有机会要重新写个好一点的主题。

嗯,来数数这篇文章里一共立了多少 flag。

把博客迁移到 VeriPress 了

情人节要到了,手把手教你写个 QQ 机器人给女朋友玩

创建于
分类:DevDetailed
标签:酷QQQ BotMojo-WebqqHTTP API

其实 QQ 机器人写起来很简单的,对于本教程中使用的 QQ 机器人框架,你需要一点点 C/C++ 基础,或者了解其它任何语言的 HTTP 库(开启 HTTP 服务端、发起 HTTP 请求两种)的使用。

QQ 机器人框架简介

也就是对 QQ 协议分析之后封装出来的一个完整的 QQ 客户端及开发框架,通过对这个客户端的事件的处理和接口的调用,即可实现诸如自动回复、主动通知等功能。

目前网上各种机器人框架很多,本教程主要以 酷 QMojo-Webqq 为例。

这两个框架差别还是蛮大的:酷 Q 是闭源的,使用 Android QQ 协议,似乎是易语言写的,只能在 Windows 上跑(最新版本也支持在 Wine 里面跑),且必须在图形界面操作,官方提供易语言和 C++ 的 SDK;Mojo-Webqq 是开源的,使用 SmartQQ 协议,用 Perl 写的,全平台基本都能跑,比较方便用脚本来自动化,官方提供 Perl 的接口以及 HTTP 接口。

另外,酷 Q 由于是 Android QQ 协议,要比 SmartQQ 稳定很多,且可以接收图片、语音等。

这两者的差别还有很多,可以分别去看它们的文档。

下面分别讲如何使用这两个客户端框架来编写简易的 QQ 机器人。

……

情人节要到了,手把手教你写个 QQ 机器人给女朋友玩

写给新的一年

创建于
分类:Misc
标签:闲扯

因为需要重新换宽带套餐,今天把网关了,于是也有了时间来写这个年终总结暨新年展望。

2016

2016 年对我来说是进步最多的一年。我希望每年都是这样,最好进步幅度更大。

Android

其实回头翻看 Projects 文件夹里的东西、看这一年的日记,才发现自己居然学了好久的 Android 开发,可是还是欠缺很多,demo 的东西一大堆,却没有一个像样的完整的 app,那个所谓的清心天气也早已觉得烂到不行。勉强能算还行的项目可能只有 DBox 和 FusionCache 吧,后者其实也并没有什么技术含量。最终没能坚持学 Android,上一次写 Android 代码已经是 9 月份了,一个烂尾的 app。

就这种水平我居然还尝试投了几个简历,自然全是石沉大海。

Python

BlogA - Created: Friday, February 5, 2016 at 20:58

1 月 28 号创建了 Test,2 月 5 号创建了上面这个 BlogA 项目,这个时间开始尝试写 Python。现在回忆起来,这时候应该是,刚学了一些 Android,然后寒假就没有继续学,转而学了点 Python,之后下一学期开始后的某个时间又开始继续学 Android。

总之,刚学了几天 Python 之后写的这个 BlogA 竟然成了可能是目前为止自己写的最好的一个项目之一,也可能是维护时间最长的之一,而且自己的博客以及 Fenkipedia 也正在用它跑。之后又写了 BlogNG 和 BlogT,分别是前端、主题集,共同构成 BlogTANG 系列,你可以轻松地看出,这个命名是故意的。

后来也写了个学校学生门户网站的爬虫+重新封装的 API,当时还想着后续再重新写个前端、移动端,但是结果因为学校网站请求实在太慢,调用一个 API 要 10 秒多,就放弃了。其实部分也是因为懒,写完 API 之后,激情已经不在这上面了,其实也有其它方案获取信息,比如抓掌上校园 app 的包,反正是没有动力继续了。也许以后会重新来做吧。

Python 也尝试投了一个简历,DaoCloud,面试没过,十分糟糕,这次面试也让我知道了自己的能力还差多少。

……

写给新的一年

BlogA 添加 Webhook 回调的支持

创建于
分类:Misc
标签:BlogAWebhookBackend

刚刚给 BlogA 支持了 Webhook 回调,其实也就是开了一个支持 POST 的 URL 然后去执行自定义脚本而已。

因为之前把博客的内容和 BlogA 框架本身分离了,内容放在 richardchien/blog-content,然后 BlogA 跑在 docker,后台用脚本每 100 秒 pull 一次,不过这样还是有一种很不爽的感觉,于是这次直接加了 Webhook 回调,在 GitHub 添加一个 Webhook 然后在发生 push 时通知 BlogA,从而执行我的更新博客内容的脚本,这样看起来要清爽很多。

所以这篇就算水完了……主要算是测试一下效果。

BlogA 添加 Webhook 回调的支持

利用 JSONP 实现跨站请求的方法及原理

创建于
分类:Dev
标签:JSONPJavaScriptFrontendBackend跨站请求

因为之前想解决博客前后端对接时候跨站请求的问题,于是看到可以用 JSONP 来实现,研究了一番之后做一下笔记。

实现方法

要实现跨站请求是需要同时牵扯到前后两端的代码的。

后端

首先需要修改后端,这边以 Flask 为例:

from functools import wraps
from flask import Flask, request, current_app, jsonify

app = Flask(__name__)


def support_jsonp(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        callback = request.args.get('callback', False)
        if callback:
            content = str(callback) + '(' + f(*args, **kwargs).data.decode('utf-8') + ')'
            return current_app.response_class(content, mimetype='application/json')
        else:
            return f(*args, **kwargs)

    return decorated_function


@app.route('/test')
@support_jsonp
def test():
    return jsonify({'abc': 1, 'def': 2})

这边 support_jsonp 装饰器会判断是否是 JSONP 请求,如果是,则返回相应的「特殊」数据(具体在下面原理的地方详细讲),否则就按正常的请求处理。

前端

后端改完之后,前端就可以来请求了,这边先以 jQuery 的 ajax 函数为例:

$.ajax({
    url: 'http://api.example.com/test',
    dataType: 'jsonp',
    type: 'get',
    success: function(data) {
        console.log(JSON.parse(data));
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        console.log('failed');
    }
});

这样就可以成功请求到跨站的 JSON 了。

……

利用 JSONP 实现跨站请求的方法及原理

FusionCache 实现思路和使用方法

创建于
分类:DevDetailed
标签:AndroidFusionCacheCache

前几天看《Android 开发艺术探索》关于 Bitmap 加载的那章,里面讲解了一个内存和磁盘二级缓存的 ImageLoader 的实现方法,然后就突然想自己写一个内存+磁盘的混合缓存框架,正好平时上课闲得慌,就在课上构思,最终在昨天完成了这个 FusionCache。虽然注释写得挺多,但还是怕以后看不懂,所以这里记录一下实现思路。

实现思路

首先这个缓存应该基于键值对,使用起来方便嘛,作为一个缓存,本身就是为了增强应用使用体验而用的,并不是什么逻辑上的核心部件,那么就应该用起来越简单越好。

并且缓存应当可以分别设置内存和磁盘缓存的容量上限,也就是说要计算每个对象在内存和磁盘中所占空间。

由于不是所有类的对象都能存到磁盘中,也不是所有对象都能成功计算内存占用,所以需要限制支持存入缓存的对象类型,参考 ASimpleCache,支持 StringJSONObjectJSONArraybyte[]BitmapDrawableSerializable

……

FusionCache 实现思路和使用方法

在 OS X 上编译 AOSP 源码

创建于 更新于
分类:MiscDetailed
标签:AndroidAOSP

昨天本来是想把 AOSP 的源码下下来方便查阅的,然后莫名其妙就突然打算自己编译一下试试,然后就编译了,中间遇到一些坑,在这里记录一下。

1. 准备环境

按道理来说官方是推荐用 Ubuntu LTS 来编译的,不过我也没装,所以就用 OS X 了,AOSP 官网也是有 OS X 的环境配置教程的(Setting up a Mac OS build environment)。过程基本和官网的教程一致。

1.1 创建区分大小写的分区

OS X 默认的文件系统是「case-preserving but case-insensitive」的,也就是文件名保留大小写,但实际并不区分,而 AOSP 建议用区分大小写的文件系统,于是需要创建新分区,运行:

hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 100g ~/android.dmg

-type SPARSE 表示在使用中动态增加镜像的大小(而不是一次性占满),-size 100g 指定大小,官方声称「A size of 25GB is the minimum to complete the build」,不要信,我一开始创建的 50GB 都不够用,建议至少 100GB。

之后 ~ 目录(当然这个目录可以自己指定)下会生成一个 android.dmg.sparseimage。如果后期发现不够用,需要扩大空间,运行下面命令(注意别忘了先推出镜像):

hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage

……

在 OS X 上编译 AOSP 源码

用 Let's Encrypt 免费签发 SSL 证书

创建于 更新于
分类:Ops
标签:SSLLet's Encrypt

昨天尝试给博客加上了 SSL,用的 Let's Encrypt,这玩意可以免费签发有效期 90 天的 SSL 证书,使用也挺简单的,这里总结一下。

安装 Let's Encrypt

git clone https://github.com/certbot/certbot
cd certbot
./certbot-auto

第一次执行 ./certbot-auto 会安装各种依赖环境,会比较慢。

如果你用的是 Apache,那么直接 ./certbot-auto --apache 就会全自动配置,中间会提示你选择需要开启 SSL 的站点之类的。如果你用的是其它服务器软件或者需要手动获取证书,看下面。

获取 SSL 证书

这里只讨论 Manual 模式

首先要把需要签证书的域名解析到当前服务器的 IP,这里以 ssl.r-c.im 演示,然后运行 ./certbot-auto certonly --manual -d ssl.r-c.im,这里 ssl.r-c.im 换成要签的域名,也可以同时签多个域名,只需要加多个 -d 选项,如 ./certbot-auto certonly --manual -d ssl.r-c.im -d ssl2.r-c.im

……

用 Let's Encrypt 免费签发 SSL 证书