dig deeper, do different

2013-05-21
tolua++:namespace导致的问题

在用 cocos2d-x 的时候,可以把自己的类和 cocos2d-x 的类混在一起,即简单的把自己需要导出的类放到 cocos2d的 pkg 文件中。

网上也有推荐这样的做法,但是这样虽然简单,却让人难以接受。

我选择了比较麻烦的一种,就是自己重新定义 pkg 文件,并且导出了一个独立的cpp文件。摸过一些简单的坑之后,还算比较顺利,只是在pkg文件中没有注意处理 cocos2dnamespace,导致了在lua脚本中,自定义类中获得的比如 CCNode 之类的对象后无法访问其成员函数而已。

具体的原因,因为在cocos2d-x的pkg中,它是删除了namespace的,所以tolua++生成的代码是这样的:

1
tolua_usertype(tolua_S,"CCNode");

而在我的pkg文件中,由于没有处理namespace,生成的代码如下:

1
tolua_usertype(tolua_S,"cocos::CCNode");

这就导致了同一个类在lua脚本中被认为是两个不同的对象。

解决的方法很简单,去掉namespace即可。

Read More

2013-04-19
指针vector初始化

C++中,在申明的时候初始化一个vector的时候可以指明vector的大小和默认值。但是如果用NULL来初始化指针的时候,会遇到问题。

class A;
vector<A > vtTest<2, NULL>;

在XCode中报错:说不能把int型赋值给A。原因就是NULL本身是不带具体的类型的,默认会被认为是一个int类型。

所以,解决的方法就是类型强制转换。

Read More

2013-03-20
Ubuntu下部署Jenkins的一些要点

Jenkins是一个开源的持续集成的工具,安装什么的都没有问题,非常简单。但是在配置的时候还是遇到了几个问题:

  1. 配置权限管理的时候,一定要先创建一个用户之后再进行。如果没有创建用户,又去掉了”Allow users to sign up”的勾,那么只能去编辑config.xml了。

  2. jenkins用户需要提升到root权限来进行一些操作。先把他加入到root group,再编辑/etc/sudoers设在sudo的时候不需要密码。

    1
    2
    $ sudo gpasswd -a jenkins root
    $ sudo vim /etc/sudoers

在sudoers中加入

1
jenkins ALL=NOPASSWD:ALL

当然,也可以使用expect工具来提升脚本执行时的权限

  1. 多个命令执行的时候,无法正确的反映执行的状态,往往其中已经出现错误了,jenkins还是返回成功。这个问题可以通过检查每个命令的返回值来处理,比如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/bin/sh
    sudo make clean
    if [ $? -ne 0 ]; then
    exit 1
    fi
    sudo make
    if [ $? -ne 0 ]; then
    exit 1
    fi
    sudo make install
    if [ $? -ne 0 ]; then
    exit 1
    fi
Read More

2013-03-18
Ubuntun下GIT服务器的建立

使用环境:小团队

安装openssh-server, git

1
2
sudo apt-get install git
sudo apt-get install openssh-server

添加git账号

这儿方案中,所有的人共享一个账号,即git账号:
sudo adduser git
按照提示设置账号内容,密码等。

配置登陆认证

使用公钥来避免每次都需要输入密码的麻烦。可以给每个用户配置一个不同的公钥。

这里直接在Ubuntu上为用户生成公钥-密钥对,把公钥加入认证文件,密钥发给用户。
ssh-keygen
为不同的用户指定不同的文件名,比如:id_rsa.wxue,将生成id_rsa.wxue和id_rsa.wxue.pub。

1
2
cat .ssh/id_rsa.wxue.pub
/home/git/.ssh/authorized_keys

这些密钥可以用来登陆git账号了。

创建GIT仓库

把git的仓库放在/opt/gitrepo下

1
2
3
4
5
6
cd /opt
mkdri gitrepo
cd gitrepo
mkdir project.git
cd project.git
git --bare init

修改权限

现在git账号的权限,只能做git相关的操作
sudo vim /etc/passwd
把git的shell从/bin/bash改为/usr/bin/git-shell

客户端配置

  1. 说说在osx下的配置,其他linux系统也是一样。
    把相关用户的密钥放在它电脑的.ssh目录下,然后编辑或是创建config文件
    $ vim ~/.ssh/config
    在config文件中加入如下内容:
    1
    2
    Host 192.168.1.222 192.168.1.222
    IdentityFile ~/.ssh/id_rsa.wxue

如果只有一个id_rsa密钥文件,也可以不创建config文件。

修改config文件的属性
$ chmod 644 ~/.ssh/config
文件的目录也可以做一下限制,只有git帐号才可以打开:
$ sudo chown git:git gitrepo

  1. windows下的配置
    Windows下一般使用图形化工具TortoiseGit。TortoiseGit如果使用plink则无法使用id_rsa,需要转换从PuTTY Key Generator格式的ppk密钥。在TortoiseGit目录下可以找到PuTTY Key Generator工具,把id_rsa导入进去,并保存成ppk文件,放在用户目录的.ssh目录下。

还没完,还需要在TortoiseGit目录中找到Pageant程序,把ppk文件加入到里面。或者,在添加remote的时候,把ppk绑定进来。

Read More

2013-03-13
Lua与C/C++的一些简单交互

我只写简单的!

  • lua版本 5.1.4
  • 环境 ubuntu 12.04

从C/C++调用lua中自定义的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <lua.hpp>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
lua_State *L = luaL_newstate();
luaopen_base(L);
luaL_openlibs(L);
int ret = luaL_dofile(L, "test.lua");
if (ret != 0)
{
cout << "load test.lua failed" << endl;
return 1;
}
lua_getglobal(L, "showValue");
lua_pushstring(L, "William");
lua_pushstring(L, "Hsueh");
lua_pcall(L, 2, 0, 0);
lua_close(L);
return 0;c++
}

test.lua文件:

1
2
3
function showValue(strFirstName, strLastName)
print(strFirstName .. "." .. strLastName)
end

从lua中返回一个值给C/C++

main.cpp,注意lua_pcall中设置了返回3个值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <lua.hpp>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
lua_State *L = luaL_newstate();
luaopen_base(L);
luaL_openlibs(L);
int ret = luaL_dofile(L, "test.lua");
if (ret != 0)
{
cout << "load test.lua failed" << endl;
return 1;
}
lua_getglobal(L, "showValue");
lua_pushstring(L, "William");
lua_pushstring(L, "Hsueh");
lua_pcall(L, 2, 3, 0);
int nOld = lua_tonumber(L, -1);
const char *pIs = lua_tostring(L, -2);
const char *pName = lua_tostring(L, -3);
cout << pName << " " << pIs << " " << nOld << endl;
lua_pop(L, 3);
lua_close(L);
return 0;
}

test.lua文件返回了3个值

1
2
3
4
5
function showValue(strFirstName, strLastName)
strName = strFirstName .. "." .. strLastName
print(strName)
return strName, "is", 18
end

Lua调用C/C++中自定义的函数

Lua不能调用任意的C/C++函数。可以向Lua中注册的函数,需要符合以下的规范:
typedef int (*lua_CFunction) (lua_State *L);
main.cpp,定义了一个名为lua_printValue的函数,并且注册为PrintValue的lua函数,以便于在Lua中使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <lua.hpp>
#include <iostream>
using namespace std;
int lua_printValue(lua_State *L)
{
// get the parameter
const char *pValue = lua_tostring(L, -1);
// do something here...
lua_pushstring(L, pValue);
lua_pushstring(L, "Year");
// return 2 value
return 2;
}
int main(int argc, const char * argv[])
{
lua_State *L = luaL_newstate();
luaopen_base(L);
luaL_openlibs(L);
// register the lua_printValue function
// as PrintValue which can be used in lua
lua_pushcfunction(L, lua_printValue);
lua_setglobal(L, "PrintValue");
int ret = luaL_dofile(L, "test.lua");
if (ret != 0)
{
cout << "load test.lua failed" << endl;
return 1;
}
lua_getglobal(L, "showValue");
lua_pushstring(L, "William");
lua_pushstring(L, "Hsueh");
lua_pcall(L, 2, 3, 0);
int nOld = lua_tonumber(L, -1);
const char *pIs = lua_tostring(L, -2);
const char *pName = lua_tostring(L, -3);
cout << pName << " " << pIs << " " << nOld << endl;
lua_pop(L, 3);
lua_close(L);
return 0;
}

test.lua文件:

1
2
3
4
5
6
function showValue(strFirstName, strLastName)
strName = strFirstName .. "." .. strLastName
strThis, strYear = PrintValue("this")
strAge = strThis .. " " .. strYear .. " is"
return strName, strAge, 18
end

PrintValue从Lua中接受一个参数,在C/C++中处理了一下,返回两个参数给Lua。

Read More