0%

我们需要有一个数据表来保存用户的提币请求和处理状态,基本数据内容如下:

id 提币地址 提币金额 提币序列号 提币状态
1 0xa 0.11 c39b6ff7-b787-41a5-a3e5-d086c80acd3c 0
2 0xb 0.12 c39b6ff7-b787-41a5-a3e5-d086c80acd3d 0
3 0xa 0.08 c39b6ff7-b787-41a5-a3e5-d086c80acd3e 0
4 0xc 0.17 c39b6ff7-b787-41a5-a3e5-d086c80acd3f 0

数据表结构具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE `t_withdraw` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`to_address` varchar(128) NOT NULL DEFAULT '' COMMENT '提币地址',
`balance_real` varchar(128) NOT NULL DEFAULT '' COMMENT '提币金额',
`out_serial` varchar(64) NOT NULL DEFAULT '' COMMENT '提币唯一标示',
`tx_hash` varchar(128) NOT NULL DEFAULT '' COMMENT '提币tx hash',
`create_time` bigint(20) unsigned NOT NULL COMMENT '创建时间',
`handle_status` int(11) NOT NULL COMMENT '处理状态',
`handle_msg` varchar(128) NOT NULL COMMENT '处理消息',
`handle_time` bigint(20) unsigned NOT NULL COMMENT '处理时间',
PRIMARY KEY (`id`),
UNIQUE KEY `out_serial` (`out_serial`),
KEY `t_withdraw_tx_hash_idx` (`tx_hash`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

之后我们需要一个热钱包,这里面储存着部分资产用于转账给用户。

阅读全文 »

理解以太坊(eth)需要理解其中比较重要的几个概念

cocos2d-x中使用的luajit的库是预编译也就是prebuilt的,
但是这个预编版本并没有启用5.2的特性,也就是说

  • pairs() and ipairs() check for __pairs and __ipairs

这个特性是不被支持的.

我需要在项目中使用 cloudwu/pbc
这个protobuf的lua解析库,这在个库中,用到了5.2的这个特性

查看pbc的源码 __pairs使用源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local function expand(tbl)
local typename = rawget(tbl , 1)
local buffer = rawget(tbl , 2)
tbl[1] , tbl[2] = nil , nil
assert(c._decode(P, decode_message_cb , tbl , typename, buffer), typename)
setmetatable(tbl , default_table(typename))
end

function decode_message_mt.__index(tbl, key)
expand(tbl)
return tbl[key]
end

--调用pairs的时候会调用expand函数,用于解析下一层消息
function decode_message_mt.__pairs(tbl)
expand(tbl)
return pairs(tbl)
end

从源码中我们可以看出,pbc对于protobuf的解析并不是全部解析的,
也就是说,遇到message嵌套的情况,初始只
解析一层消息,
当代码调用下一层消息的__index__pairs元函数的时候,
才会进行下一层消息的实际解析

那么问题来了,当这个库用在cocos2d-x上的时候,我们在

1
for k, v in pairs( msg ) do

的时候,是不会调用到expand方法的,这样获取的消息内容当然也就不正确了

为了能顺利的使用pbc库,我们需要启用luajit的这个特性

根据luajit官网说明lujit/extensions,
可以通过编译时加入预定义LUAJIT_ENABLE_LUA52COMPAT宏来启用这一特性.

cocos2d-x 3.0rc0版本为例,luajit的源码路径为cocos2d-x-3.0rc0/external/lua/luajit,
使用的luajit版本为2.0.1-hotfix,源码中已经打好了hotfix的包.

并且在根目录下提供了

  • build_android.sh
  • build_ios.sh
  • build_mac.sh

三个编译脚本用来生成不同平台的预编译库

但是,恩,但是,源码里不知道为何把Makefile文件删除了.

我们需要去官网下载2.0.1版本的luajit源码,然后把两个Markfile文件,
拷贝到cdx对应的目录下. 注意,有两个Markfile,luajit源码的根目录下一个,
src目录下一个.

##首先在windows平台下进行编译

windows平台的编译脚本是cocos2d-x-3.0rc0/external/lua/luajit/src/src/msvcbuild.bat

  1. 修改msvcbuild.bat文件,找到@set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE,
    添加编译参数,更改为@set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE /DLUAJIT_ENABLE_LUA52COMPAT
  2. 不能在命令行直接调用这个bat脚本,因为需要vs编译环境参数,打开vs的命令行工具.
    命令行工具
    命令行工具
  3. 切换到编译脚本所在路径,运行msvcbuild.bat完成编译

编译成功后会生成

  • luajit.exe 用于编译lua脚本的工具
  • lua51.dll 库文件
  • lua51.lib 库文件

##windows版本的编译没有使用Makefile文件,但是其他版本的编译都使用了Makefile文件,所以我们直接把编译参数在Makefile里更改就可以了

cocos2d-x-3.0rc0/external/lua/luajit/src/src中找到刚改从luajit源码中拷贝过来的Makefile.
找到#XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT,把注释取消,XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT.

##ios版本的编译

打开build_ios.sh文件,根据自己xcode的版本修改成自己的参数

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LIPO="xcrun -sdk iphoneos lipo"
STRIP="xcrun -sdk iphoneos strip"

SRCDIR=$DIR/src
DESTDIR=$DIR/prebuilt/ios
IXCODE=`xcode-select -print-path`
ISDK=$IXCODE/Platforms/iPhoneOS.platform/Developer
ISDKVER=iPhoneOS7.1.sdk #xcode中iPhone sdk的版本
ISDKP=/usr/bin/ #gcc所在路径,注意,低版本的可能在XCode路径下

然后执行就好了

##mac版本的编译和ios差不多,而且不用更改编译脚本

##android版本的编译

首先要在系统上安装ndk,并且设置NDK_ROOT环境参数,因为编译脚本要用到

打开build_android.sh文件,修改相应的参数

1
host_os=`uname -s | tr "[:upper:]" "[:lower:]"`      #要注意host_os的设置,因为如果这windows上使用cygwin编译,

这个参数需要更改为windows

1
2
3
4
5
NDK=$NDK_ROOT
NDKABI=8
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.6
NDKP=$NDKVER/prebuilt/${host_os}-x86/bin/arm-linux-androideabi- #需要注意-x86,如果使用的是64位的ndk,需要更改为-x86_64
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
1
2
3
4
5
# Android/x86, x86 (i686 SSE3), Android 4.0+ (ICS)
NDKABI=14
DESTDIR=$DIR/prebuilt/android/x86
NDKVER=$NDK/toolchains/x86-4.6
NDKP=$NDKVER/prebuilt/${host_os}-x86/bin/i686-linux-android- #同上,根据ndk的版本进行修改

编译后就能获得android版本的库了

所有库编译完成后,我们就可以在各个平台的luajit中支持5.2的这些特性了

这个脚本的主要作用就是设置cocos2d-x所需要用到的环境变量,
其中包括:

  • COCOS_CONSOLE_ROOT cocos2d-x的各种脚本的路径
  • NDK_ROOT
  • ANDROID_SDK_ROOT
  • ANT_ROOT ant工具的路径,bin文件夹的路径

COCOS_CONSOLE_ROOT是不需要手动添加的,脚本会自动检测其路径
如果你的环境中已经存在了如上路径,可以忽略相应的参数

  • 如果当前环境为win32,则修改注册表,添加环境变量
  • 如果不是,则把变量设置数据写入.bash_profile``bash_login``.profile这些相应的文件

至于生效的问题

  • 所以无论在win32环境需要重启命令行使环境变量生效
  • 在unix环境需要source相应的文件使环境变量生效,下一次启动终端将自动执行这些命令

首先调用的是LuaEngine的init()方法,
LuaEngine::init首先初始化了LuaStack,
然后去加载被被标记为过时的lua api库

其实主要的lua初始化过程在LuaStack

LuaStack::init中首先创建luastate,
然后加载基础类库,
之后加载tolua++的fix.

再之后就开始注册cocos2d-x在lua中所能使用的函数了

首先注册的是print函数,这里需要特别注意
*luaL_register的调用会在lua栈中push进_G这个table*

在之后register_all_xxx的时候会调用一个tolua_module的函数,
而这个函数会用到栈顶的_G这个table.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (name)
{
/* tolua module */
lua_pushstring(L,name);
lua_rawget(L,-2); //看见这里了吗?这里实际上是在luaL_register时候添加到栈里的
if (!lua_istable(L,-1)) /* check if module already exists */
{
lua_pop(L,1);
lua_newtable(L);
lua_pushstring(L,name);
lua_pushvalue(L,-2);
lua_rawset(L,-4); /* assing module into module */
}
}

这也就是为什么我们在自己的函数中使用相同的方式register_all_xxx的时候会报错的原因,
因为_G已经不在栈里了

其他部分都可以通过读源码了解,但是这个tolua_module_G表的使用方式感觉多少有些不恰当

在windows下使用TextField控件,退格键是不起作用的
这是因为CCGLView.cpp中通过监听GLFWChar来操作字符
但是退格键左右操作字符是不在这个函数回调的
但是CCGLView监听的GLFWKey并没有调用IMEDDispatch的dispatchDeleteBackward函数用于处理退格
是为了让我们自己控制退格键的作用?
解决方案有两个
1.修改CCGLView源码,在GLView::onGLFWKeyCallback函数中添加

1
2
3
4
5
6
7
if (GLFW_KEY_BACKSPACE == key)
{
if (GLFW_REPEAT == action || GLFW_PRESS == action)
{
IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
}
}

2.自己监听KeybordEvent,在退格处理用调用IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward()
但是第二种方法的问题是不能处理按键的GLFW_REPEAT事件,也就是一直按下退格无法连续删除文字