全国哀悼日
今天是全国哀悼日,为悼念在5月12日四川汶川地震中去遇难的同胞。
其实这几天里,对我触动很大,经常会莫名的悲伤和失落,有感于生命的渺小,脆弱和坚强。
但愿死去的人可以安息, 生还的同胞可以重建家园…
今天是全国哀悼日,为悼念在5月12日四川汶川地震中去遇难的同胞。
其实这几天里,对我触动很大,经常会莫名的悲伤和失落,有感于生命的渺小,脆弱和坚强。
但愿死去的人可以安息, 生还的同胞可以重建家园…
Rhino是一个开源的JavaScript实现,它完全使用Java语言开发,可以用于嵌入到Java应用程序中以向终端用户提供脚本功能。
根据官方网站 ( http://www.mozilla.org/rhino/ ) ,有下面的特征
其实N年之前就听说过它了,只是一直没有想起来要应用,昨天突然遇到一个问题,用其他语言不太方便解决,就是要在服务器端模拟网页内的JS运行,来获取一定的信息(提供给爬虫用),所以突然想到这个东东,试了一下下,还蛮有趣的,下面是一些记录:
这里主要用到 它的shell环境
在ubuntu 里面
apt-get install rhino
后,可以用 rhino命令直接运行 rhino shell
rhino本身提供了一些可以功我们使用的容器对象和方法,比如 print 就是将字符串输出到标准输出上…
rhino -e ‘ [ javascript code] ‘ 可以用来直接执行一段javascript代码,比如:
又比如一个实际的例子,针对 56.com 的视频结果页面id获取,我们可以进行测试一下, 如下面的地址:
http://www.56.com/u93/v_MzM3NzcwMzQ.html
检查它的 “更多分享代码“ 连接 : http://www.56.com/u93/share.php?id=33777034&p=1 里面的33777034就是视频的id,但是我们并不能直接通过源代码取到这个信息,因为这个链接是在js里面生成的,所以如果我们是后台的程序去读取的话,比如一个爬虫,就不能完整的进入并爬取这个地址,要解决这个问题,我们可以用rhino来实现对这类js的解释执行,得到id (当然如果在前端,直接用firebug更方便一些), 具体的方法我就不将了,可以看下面我简单提取的一段js代码,当然,是可以用rhino执行的
结果如下
解析上面的json就可以取到可爱的id了…
哈哈,一个项目可能会用到,记录一下下吧,我对插值算法了解不多,下了一个最简单的线性插值算法实现:http://www.codecogs.com/cog-79
然后由于是仅对X轴的伸展,所以再在结果上除去一个因子就可以了
代码照它给的例子改的
#define N 12
int main()
{
// Declare and initialize two arrays to hold the coordinates of the initial data points
double x[N], y[N];
// Generate the points
for (int i = 0; i < N; ++i) {
x[i] = i;
y[i] = 2*i;
}
cout << " Source : " << endl;
for (int i = 0; i < N; i++) {
cout << setw(5) << i << ": " ;
cout << "x = " << x[i] << " y = ";
cout << setw(13) << y[i] << endl;
}
// Initialize the linear interpolation routine with known data points
Maths::Interpolation::Linear A(N, x, y);
// Interrogate linear fitting curve to find interpolated values
int N_out = 14;
double factor = ((float)N_out / (float)N);
cout << " Dest : " << endl;
double xx;
for (int i = 0; i < N_out; ++i) {
xx = (i/factor < N - 1) ? i/factor : N - 1;
cout << setw(5) << i << ": " ;
cout << "x = " << setw(7) << xx << " y = ";
}
return 0;
}
结果
rainx@RainX:/tmp$ ./test
Source :
0: x = 0 y = 0
1: x = 1 y = 2
2: x = 2 y = 4
3: x = 3 y = 6
4: x = 4 y = 8
5: x = 5 y = 10
6: x = 6 y = 12
7: x = 7 y = 14
8: x = 8 y = 16
9: x = 9 y = 18
10: x = 10 y = 20
11: x = 11 y = 22
Dest :
0: x = 0 y = 0
1: x = 0.857143 y = 1.71429
2: x = 1.71429 y = 3.42857
3: x = 2.57143 y = 5.14286
4: x = 3.42857 y = 6.85714
5: x = 4.28571 y = 8.57143
6: x = 5.14286 y = 10.2857
7: x = 6 y = 12
8: x = 6.85714 y = 13.7143
9: x = 7.71429 y = 15.4286
10: x = 8.57143 y = 17.1429
11: x = 9.42857 y = 18.8571
12: x = 10.2857 y = 20.5714
13: x = 11 y = 22
很久没有写blog了…. 但是这段时间却经历了很多事情… 开始由于项目需要(做一个关于爬虫和搜索内容萃取的项目)去了杭州工作了一段时间, 然后又由于财经频道的紧急开发任务回到北京,加入财经开发,然后又一个人去了一趟青岛旅游放松,又过了一个星期去了一趟葫芦岛玩, 接着由于紧急人物开始了封闭开发.. 大约快一个月了吧..我又由于另外一个项目提前结束封闭开发, 终于可以安心的在家里写写blog轻松一下了..
这次是我第一次经历封闭开发的项目,感触很多。我们每天住在一个酒店里,工作也在酒店的会议室,大家每天都在一起,彼此之前熟悉了许多..很快进入工作的状态,并一直保持的很好,这次一同封闭开发的同事里有很多新人,他们的敬业和热情给我很深的印象,但是同时又有很多问题,比如说工作时间不固定,经常晚睡晚起之类,还有吃的东西比较单调..呵呵..不过总体感觉还是不错的..很难忘一起工作的一段日子。
因为这段时间一直要和印度工程师打交道,无奈之下只好强迫自己多看写美剧提高一下英文听力,虽然之前不是很喜欢,但还是看了一下Friends,觉得不错,所以就开始一边BT下载一边看,可是BT下载起来太麻烦了,虽然一直用家里的Debian的Azureus下不会影响我工作时用的电脑,和隔壁的MM说起之后,她说刚好有一份自己下载刻录的DVD,然后就借给我了,呵呵, 但是拿到之后才发现,他的是mkv版本,我用我的Ubuntu Dapper 最新版的 mplayer (MPlayer 2:0.99+1.0pre7try2+cvs20060117-0ubuntu8 ) 配上完整的decoder,可以播放,但是没有声音,看了看错误提示:
提示大概是说音频解码出了些问题,
ok… 后来在网上发现很多人都遇到过这种情况,而且没有看到好的解决方案,不过看到一个台湾人的blog上好像提到最新版的mplayer似乎可以解决,所以在mplayer的网站上找到新版的mplayer源代码,并编译,ok..在试一下,cool,音频可以解码了,但是还是没有声音,因为貌似新版的mplayer编译出了问题,没有找到音频设备,faint, ok.. 我对linux的音频设备没有太多的了解,所以只能想另外的办法了,
那就是,如果新版本的音频视频都可以解码,那我就可以用新版本的mencoder将文件转码成就的mplayer可以播放的格式,ok.. 然后用旧的mplayer来播放 :
当然,如果想批量处理一个目录下的,可以试下面的语句,
然后再播放, 成功了,cool.. 但是还有一个问题,就是mkv格式是将字幕集成的,但是转为avi之后,就失去了字幕的信息,不过还好,可以从这个网站上下载到完整的字幕, 然后在mplayer的时候加上字母的信息
ok… 最后,为了支持中文,你最好配置一下 ~/.mplayer/config
SIMSUN.TTF 是你汉字字体的位置

《动摇》是一部很不错的片子,和其他日本的文艺片一样,这个片子有点平淡甚至压抑,但是很真实。哥哥埝和弟弟猛代表了两种类型,两种风格的人,亲情的羁绊让他们联系在一起,表面上看来,生活对于两个人之间是非常不平衡的,弟弟拥有很多哥哥没有的东西(让人羡慕的工作,都市里的生活),并且逃避了很多应尽的责任,最后他的证词还亲手把哥哥送进了监狱。
但实际上呢,其实我想其实两个人之间又在摇摆中维系着一种平衡,其实两个人都有各自逃避的东西,记得在猛在审判之前去探望埝是,猛说他自己一直在逃避,埝说,”逃避毫无意义的生活,对吧?”,在埝的意识里,他显然已经认定了自己生活的平淡,实际上,他主动向警察自首也是在逃避,逃避平淡的生活。 另外一点,”人生的意义?” 这种问题又有几个人能真正的解释呢? 事实上,对于生活中的每个人来说,又有几个不是在逃避呢? 消极的人,逃避责任,逃避挑战。 积极的人, 逃避平凡,逃避不安全感。所以,逃避的人生会不会也是无限接近常道的道的其中一个呢?
前段时间做了一个项目,项目是封装我们公司现有的一个用c++实现的一个消息中间件,使其可以让perl程序员使用,这个消息中间件是一个用TCP和共享内存实现实现的一个异步消息传输的中间件,分为两个部分,其中客户端可以调用某函数发送消息,服务器端会自动监听并且调用一个callback函数来处理这个请求, 其中客户端的封装美国部门已经用 perlxs实现了, 服务器端的程序是我来写的, 这里用到了perlembed的技术,因为服务器端程序和客户端不同,不是perl去调用c/c++的函数,二十c++去调用perl,所以我们需要将c++中嵌入perl的解释器。关于那个项目具体的情况我就不说了,这里我主要写一下c/c++中嵌入perl解释器和调用perl函数的方法…(给自己做一个备忘)
其实,大部分的内容可以从相关的perldoc中找到..
perldoc perlembed
首先是编译的参数,在这里,如果需要嵌入perl,我们可以通过perl的ExtUtils::Embed模块来生成连接的参数
编译参数
连接参数
ok..下面介绍一嵌入perl的解释器
很简单,看看perlembed提供的例子
static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
int main(int argc, char **argv, char **env)
{
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_parse(my_perl, NULL, argc, argv, (char **)NULL);
perl_run(my_perl);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
保存为interp.c, 然后用如下的命令编译
ok… 现在,interp就是一个简单的perl解释器了,我们可以用类似普通perl解释器的方法使用它,比如:
好的,我们现在在看一下程序,我们之前做了什么呢?
首先引入了EXTERN.h和perl.h两个头文件,这些头文件应该在perl的发行版中, 然后声明perl的解释器PerlInterpreter, 后面是我们的主程序,使用PERL_SYS_INIT3或者PERL_SYS_TERM宏提供了系统指定的一些初始化参数,注意这里的PERL_SYS_INIT3可能会改变env变量的值,所以可能将env直接传给perl_parse更合适一些
然后perl_alloc分配perl解释器,返回perl解释器的变量。
之后是perl_construct,构造perl解释器
PL_exit_flags设置perl返回值的flag
perl_parse这一句比较关键,它用来生成解析指定的perl代码,第一个参数是我们生成的perl解释器变量,
然后就是Perl_run了,用来运行解释器
之后是前面的反过程perl_destruct , perl_free
可见,运行perl解释器的步骤为
声明->准备-> 分配 ->构造 -> 解析 -> 运行 -> 析构 -> 释放 -> 终止
ok… 那么其实,大多数的情况下,我们实际上的需求并不是运行perl解释器,而是通过perl解释器,调用perl的函数,来实现我们指定的功能,如果这样的话,我们只需要把其中的perl_run替换为运行指定的perl程序就可以了。
看看perlembed里的程序
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *args[] = { NULL };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, argc, argv, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
/*** skipping perl_run() ***/
call_argv("showtime", G_DISCARD | G_NOARGS, args);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
cc -o showtime showtime.c ‘perl -MExtUtils::Embed -e ccopts -e ldopts‘
这里,我们将perl_run替换为call_argv,来调用showtime函数,所以我们需要提供一个perl程序来实现这个showtime函数,可以通过
运行测试
这里call_argv的第一个参数是函数的名字,第二个是一个flag的组合,G_DISCARD表示函数没有返回值,G_NOARGS代表函数没有代任何参数,如果你想传普通的参数给perl,可以通过一个用NULL为终止符号的参数列表传入,如果需要传入特殊的参数或者说要有返回值,perlembed提供了一种类似汇编语言调用子程序的方法,这样,我们需要自己来维护一个堆栈来处理程序的参数。
例如:
我们看这里的一个perl程序,用来做一个求幂的操作
有两个参数,并且返回结果。
ok…我们看看c语言怎样调用这个程序
static PerlInterpreter *my_perl;
static void
PerlPower(int a, int b)
{
dSP; /* initialize stack pointer */
ENTER; /* everything created after here */
SAVETMPS; /* …is a temporary variable. */
PUSHMARK(SP); /* remember the stack pointer */
XPUSHs(sv_2mortal(newSViv(a))); /* push the base onto the stack */
XPUSHs(sv_2mortal(newSViv(b))); /* push the exponent onto stack */
PUTBACK; /* make local stack pointer global */
call_pv("expo", G_SCALAR); /* call the function */
SPAGAIN; /* refresh stack pointer */
/* pop the return value from stack */
printf ("%d to the %dth power is %d.\n", a, b, POPi);
PUTBACK;
FREETMPS; /* free that return value */
LEAVE; /* …and the XPUSHed "mortal" args.*/
}
int main (int argc, char **argv, char **env)
{
char *my_argv[] = { "", "power.pl" };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct( my_perl );
perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
PerlPower(3, 4); /*** 运算 3 ** 4 ***/
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
ok… 我们可以看到,首先,这里我们并没有用系统的argc和argv来调用perl_parse,而是自己构造了一组。 my_argv,长度为2 ,第二个就是我们需要调用的程序。
然后我们自己实现了一个PerlPower函数来封装perl的调用,可以看到里面有超多的宏,很象汇编里的调用,其实我们实际调用的时候按照上面的例子来调用就可以了
dSP用来初始化堆栈的指针,
XPUSHs用来推入一个标量到堆栈中,这个也是我们最常用的,newSViv 将一个整数转换为perl的标量,sv_2mortal是对变量进行清理的时候会使用到的,
ENTER ;
SAVETMPS ;
FREETMPS ;
LEAVE ;
这些宏就是用来进行临时变量的生成和清理的。
如果说我们需要传入的参数是字符串类型的话
可以尝试下面几个函数,将他转换为标量
然后掉用,call_pv,这里的G_SCALAR的意思就是返回值为一个标量。
,然后就可以用POP[x]系列的宏将返回值pop出来了,如果直接返回标量就为 POPs, 返回整数POPi , 指针POPp …
如果返回的参数为字符串,可以用SvPV(SV*, STRLEN len)宏进行还原(这里是一个宏,所以不用使用&len).
关于编程方面,应该就这些了,还有一些要注意的地方,
我们这里比较麻烦的是,当在c里面调用perl解释器,但是解释器又调用一个c写的扩展时,我们的程序就会出问题,这里具体的原因我就不说了, 解决方法是实现xs_init callback函数,引入DynaLoader
用 perl -MExtUtils::Embed -e xsinit 生成perlxsi.c
然后在调用perl_parse时加入这个参数
将他们编连在一起就ok了
当然了,不要忘了在你的主程序的头文件中加入 EXTERN_C void xs_init (pTHX); 的声明
带有dynaloader的power
ok….其实perlembed涉及的内容很多,这里就不深入的介绍了,上面是我上次的项目中用到的一些,应该也是相对常用的一些技术,由于时间过了很久,我也忘的差不多了,更多的内容请参考下面perldoc几个文档
perlembed, perlguts, perlcall, perlxs, perlapi
其实之前做Solor的时候有用过这个,但是不是PHP版本的..而是直接调用MrBrownstone的C语言版本,后来还做成了PHP extension ,但后来由于服务器到期的原因,换了服务器,新的服务器我没有root或sudo的权限,不能直接在服务器上放置应用程序,安装自己的PHP extension了,所以也导致solor关闭了,当然了,solor暂时关闭也与当时公司实在比较忙有关系,昨天晚上睡觉前突然想到要重新整理一下以前的代码,突然想到这里,就想自己用PHP实现一个Script Decoder .所以就按照之前MrBrownstone的C语言版本重新编写了一个PHP的版本,呵呵,没想到改写起来还真是挺容易的,毕竟语法比较相似,我保留了之前版本的变量和函数命名。
这个是函数页面的连接 :
http://rainx1982.googlepages.com/decoderformicrosoftscriptencoder%28phpversion%29
也可以直接下载代码: jsdecoder.php
当然了,如果你有特殊的需要,希望得到PHP extension的版本的代码(运行速度上会快些),也可以和我联系(不是free的,哈哈)….
继上一次准备了PHPunit的培训之后,这两天有研究了xunit系列里的其他几个 ,如cppunit ,和 junit,发现虽然这些xunit都是声称port自junit,但各有各的特点, 相对来说phpunit和junit比较像,都有相应的命令行工具来执行, 但是cppunit就比较麻烦..还要自己写main程序,并编译执行,而且assertXxxx系列的函数在cppunit里变成了一大堆的宏,感觉怪怪的,并且cppunit里的TestSuite和其他两个同行的范围貌似也有些区别,好像一个TestSuite更像是phpunit里的一个TestCase,然后一个Runner可以同时可以执行多个TestSuite…….
除了xunit,之后还看了一些相关语言的profiling 工具, 包括php的apd,perl的 Dprof,c 的gprof,呵呵,发现相比之下php的profiling还是比其他的语言麻烦的,需要手工的修改程序加上
,而其他的profiling工具只是在编译或者运行是加一个参数就可以了..不知道以后php会不会出现更加方便的profiling工具。
随意的写些今天的收获…
今天和青炎同学讨论了一下一些异步IO,多工的一些问题 ,了解了一些以前比较关心却又一直不是很清楚的问题(虽然现在也不是太清楚),比如linux的系统调用 poll(select) 和 epoll的区别… ,青炎举了这样一个例子,类似数字电路的状态,有高电位和低电位两种, 而poll(select) 只能在电位转换之后,比如高电位转为第电位来获知状态的改变,而epoll是可以关注状态转换的事件,而不必时刻检查它的状态..so 所以这就不难理解epoll为什么在很多情况下效率很高的原因了,我想freebsd的kqueue应该也是和epoll类似的情况吧.. 顺便今天有找了一些关于epoll的链接
http://hi.baidu.com/xiexin/blog/item/5c6f55fb696a47166d22ebf0.html
然后不小心搜到云风大哥的blog上的文章
http://blog.codingnow.com/2006/04/iocp_kqueue_epoll.html
大概意思是用一些机制减少event的数量从而可以少使用epoll之类的东东.. 呵呵,btw之前都不知道云风有blog呵呵,收藏之了,我很早就看过云风的主页了(那个时候他还没有blog),里面很多有用的文章哦
相关地,让我联想到使用select ,poll作为底层实现的libevent …… 很不错的样子