Extjs自定义组件

Posted on 2012年5月30日 19:07

Extjs中的组件一般是继承自Ext.Component,如果想了解组件是如何实现的,具体可以参照Button的源代码,其是直接继承自Ext.Component的。

其中的关键属性 renderTpl 和 renderData,分别是设置模板和模板数据的属性,但是这样设置的话不灵活,不能像Button一样设置一个Text属性

就能自动设置模板中的数据,下面是参照Button实现的,在onRender回调函数中,动态的设置renderData,即将对象中的部分属性动态的添加到

renderData中。

监听Click事件的方法:

me.mon(me.el, ‘click, me.onClick, me);

所有的代码如下:

Ext.onReady (function () {

	
	Ext.define ('MydesktopIcon', {
			/* Begin Definitions */
			alias: 'widget.desktopIcon',
			extend: 'Ext.Component',
			
			width: 76,
			//height: 84,
			overCls: 'x-view-over',
			renderTpl:
				'<div class="ux-desktop-shortcut" id="{module}-shortcut">' +
				'<div class="ux-desktop-shortcut-icon">' + 
					'<img src="{iconName}" title="{name}">' +
				'</div>' +
				'<span class="ux-desktop-shortcut-text">{name}</span>' +
				'</div>' +
				'<div class="x-clear"></div>',
			
			// private
			onRender: function(ct, position) {
				// classNames for the button
				var me = this;
				// Apply the renderData to the template args
				Ext.applyIf(me.renderData, me.getTemplateArgs());
				 // Render internal structure
				me.callParent(arguments);
				//添加单击事件
				me.mon(me.el, 'click', me.onClick, me);
			},
			getTemplateArgs: function () {
				var me = this;
				return {
				   name: me.name || ' ',
				   module: me.module || ' ',
				   iconName: me.iconName || Ext.BLANK_IMAGE_URL,
				}
			},
			onClick: function(e) {
			        var me = this;
			        me.ownerCt.fireEvent ('itemClick', this);
    			},

			// inherit docs
    			initComponent: function() {
        			var me = this;
        			me.callParent(arguments);
				
			},
		});


	Ext.create ('Ext.panel.Panel', {
			title:'test',
			frame: true,
			height:800,
			renderTo: Ext.getBody(),
			items: [{
						xtype: 'desktopIcon',
						name:'首页',
						module:'firstPage',
						iconName: '../SDOJ/images/problems.png'
					},{
						xtype: 'desktopIcon',
						name:'个人信息',
						module:'firstPage',
						iconName: '../SDOJ/images/myself.png'
				},{
						xtype: 'desktopIcon',
						name:'首页',
						module:'firstPage',
						iconName: '../SDOJ/images/firstpage.png'
					},{
						xtype: 'desktopIcon',
						name:'首页',
						module:'firstPage',
						iconName: '../SDOJ/images/contest.png'
				},
				{
						xtype: 'desktopIcon',
						name:'首页',
						module:'firstPage',
						iconName: '../SDOJ/images/college.png'
					},{
						xtype: 'desktopIcon',
						name:'首页',
						module:'firstPage',
						iconName: '../SDOJ/images/letter.png'
				}],
			listeners: {
				itemClick: function (item) {
					alert (item.name)
				}
			}
				
		});


});

PHP中的错误处理

Posted on 2012年5月22日 19:58

1.php的错误等级

E_ERROR 致命的运行时错误,导致脚本的停止
E_WARNING 运行时警告
E_PARSE 语法解析消息
E_NOTICE 运行时注意消息
E_CORE_ERROR 类似E_ERROR,但不包括PHP核心错误
E_CORE_WARNING 类似E_WARNING,但不包括PHP核心错误警告
E_COMPILE_ERROR 致命的编译错误
E_COMPILE_WARNING 致命编译警告
E_USER_ERROR  用户导致的错误消息
E_USER_WARNING  用户导致的警告
E_USER_NOTICE 用户导致的注意消息
E_ALL 所有的错误、警告和注意
E_STRICT 关于PHP版本移植的兼容性和互操作性建议

2.常用错误指令

 在php的配置文件php.ini中display_errors指令控制是否显示错误信息,该指令可以由

ini_get ('display_errors')获得,而ini_set ('display_errors',1)动态设置配置文件中的改指令。

在上述的指令启动时可以设置 错误等级过滤,error_reporting指令,或者通过error_reporting函数修改。

例如:error_reporting(0);关闭错误报告

error_reporting (E_ALL);显示所有的错误报告

error_reporting(E_ALL & ~E_NOTICE);

除了上述两个指令还有下面的指令和错误有关:

 

display_startup_errors 是否显示PHP引擎在初始化时的遇到的错误信息 默认值Off
log_errors 确定日志文件的位置 Off
error_log 设置错误可以发送到syslog中 null
log_errors_max_len 设置日志的最大长度,以字节为单位,设置0表示最大长度 1024
ignore_repeated_errors 是否忽略同一文件、同一行发生的重复错误信息 Off
ignore_repeated_source 忽略不同文件中或同一文件中不同行上发生的重复错误 Off
track_errors 启动该指令会使PHP在$php_errormsg中存储最近发生的错误信息 Off

 

3.错误日志

一般发行网站后不显示错误信息,但是错误是在所难免的故可以使用错误日志。

error_reporting = E_ALL

display_errors = Off

log_errors = On

log_errors_max_len = 1024

error_log = /usr/local/error.log

在程序里面可以使用函数error_log函数发送消息,

第一个参数msg必选的,第二个是类型:

0表示发送到系统日志

1使用phpmail函数发送到邮箱,

2表示同过TCP发送到服务器

3表示将信息写到文件

windows与虚拟机下的linux通信

Posted on 2012年5月22日 14:54

1.windows 下设置一个共享文件夹,用来进行windows与linux通信的目录。

2.在linux下安装smaba服务器

3.然后mount -t smbfs -o username=war,password=198701 //192.168.0.50/share /root/windows,挂载windows下共享的目录,这样linux下就能访问windows下的目录了。

username是登陆的用户名,password是密码,然后是Ip共享的目录,要挂载的位置。

4.如果想开机自动挂载,则写个脚本放到/etc/init.d/下,然后设置开机自动运行。

char a[]和char *a的区别

Posted on 2012年5月22日 08:42

一道面试题,呵呵,没做对。

char a[100];

char *b = a;

printf ("%d %d",sizeof (a),sizeof(b));

正确的输出结果为:

100 4

二者本质上可以看为指针,可以将a赋值为b,但二者是有区别的,a是名字表示数组,而b是指针占用4个字节的指针,

编译后,对二者的访问是不同的,a是直接方位内容,加偏移,也就是a是编译时候地址就确定的,而b是指针,其内容是

放的地址,故需要先获得其地址,再访问地址指向的内容。

而在char a[]做参数的时候,a自动退化为同类型的指针。

 

还有一道面试题,做对了。

char *a = "123";

char *b = "123";

问二者的地址是否是一样的?

答案是一样的。

PHP中的include包含路径问题

Posted on 2012年4月24日 15:36

在C语言和其他语言中include某个文件一般是以包含文件的该文件所在目录为当前目录,但是php则不然,它是以顶层的php文件所在的目录为当前目录,即a包含b,b如果包含c,此时b的当前目录为a所在目录,不是b所在目录。

首先我们来看php官方手册中对include的文件搜索原则的描述:

Files for including are first looked for in each include_path entry relative to the current working directory, and then in the directory of current script. E.g. if your include_path is libraries , current working directory is /www/ , you includedinclude/a.php and there is include "b.php" in that file, b.php is first looked in /www/libraries/ and then in /www/include/ . If filename begins with ./ or ../ , it is looked only in the current working directory.

寻找包含文件的顺序先是在当前工作目录的相对的 include_path 下寻找,然后是当前运行脚本所在目录相对的 include_path 下寻找。例如 include_path 是 . ,当前工作目录是 /www/ ,脚本中要 include 一个 include/a.php 并且在该文件中有一句 include "b.php" ,则寻找 b.php 的顺序先是 /www/ ,然后是 /www/include/ 。如果文件名以 ./ 或者 ../ 开始,则只在当前工作目录相对的 include_path 下寻找。

和C语言一样php可以设置包含路径,set_include_path(), get_include_path();

下面给出一个例子,来说明php的include的使用。

a.php

<?php 

echo "current directory".getcwd()."</br>";
echo get_include_path()."</br>";
include ("include/c.php");
?>

include/c.php

<?php

echo "this is file: Include/c.php</br>";
echo "this file gcwd:".getcwd()."</br>";

include ("d.php");

?>

include/d.php

<?php

echo "this file include/d.php</br>";

echo "current directory:".getcwd()."</br>";


?>

d.php

<?php

echo "this top d.php</br>";

?>

如果d.php 和include/d.php 同时存在,

运行a.php,当前目录为网站根目录,a包含c,根据查找规则,当前目录相对的include_path优先,则查找到c。

c包含d.php文件,同样的当前目录优先,但注意此时的当前目录为a所在的目录,故查找到的d文件,为根目录下的d.php文件,如果根目录下的d文件不存在,才会查找c文件所在的目录的include_path,此时才会包含include/d.php文件。

运行效果如下:

current directory/var/www/test
.:/usr/share/php:/usr/share/pear
this is file: Include/c.php
this file gcwd:/var/www/test
this top d.php

如果根目录下的d文件不存在:

current directory/var/www/test
.:/usr/share/php:/usr/share/pear
this is file: Include/c.php
this file gcwd:/var/www/test
this file include/d.php
current directory:/var/www/test

基于DBus的进程间通信(IPC)

Posted on 2012年4月15日 21:46

最近在研究进程间通信,linux下进程间通信的方式主要有Pipe(管道),FIFO(命名管道),信号,共享内存,消息队列,信号灯等,这些方式各有各得特点,如管道是linux下命令行中常用的,用于父子进程的通信。但是这些通信方式都比较原始,要属功能最强大的IPC应该是dbus,故查看了一下dbus的资料,但是资料相对较少,特别是有关python的部分。

1.dbus概念

网上有一篇叫“D-Bus Tutorial”的文章,流传较广。

D-Bus是针对桌面环境优化的IPC(interprocess communication )机制,用于进程间的通信或进程与内核的通信。最基本的D-Bus协议是一对一的通信协议。但在很多情况下,通信的一方是消息总线。消息总线是一个特殊的应用,它同时与多个应用通信,并在应用之间传递消息。下面我们会在实例中观察消息总线的作用。消息总线的角色有点类似与X系统中的窗口管理器,窗口管理器既是X客户,又负责管理窗口。

支持dbus的系统都有两个标准的消息总线:系统总线和会话总线。系统总线用于系统与应用的通信。会话总线用于应用之间的通信。网上有一个叫d-feet的python程序,我们可以用它来观察系统中的dbus世界。

图1、由d-feet观察到的D-Bus世界

dbus还提供了两个命令行工具用于dbus测试,dbus-send和dbus-monitor,前一个命令用于测试信号的发送,后一个命令用于监控dbus的数据流。

2.dbus概念

有关dbus的基础知识不在本文的范围内,具体的参见dbus的文档。下面给出dbus常用的流程。

2.1建立服务的流程

 dbus_bus_get(),建立一个dbus连接;

 dbus_bus_request_name(),为这个dbus连接(DbusConnection)起名,这个名字将会成为我们在后续进行远程调用的时候的服务名;

然后我们进入监听循环 -- dbus_connection_read_write();

      从总线上取出消息 -- dbus_connection_pop_message();

      并通过比对消息中的方法接口名和方法名 -- dbus_message_is_method_call();

      如果一致,那么我们跳转到相应的处理中去;

      在相应的处理中,我们会从消息中取出远程调用的参数。并且建立起回传结果的通路 --      reply_to_method_call()。回传动作本身等同于一次不需要等待结果的远程调用。

2.2建立服务的流程

建立好dbus连接之后,为这dbus连接命名,申请一个远程调用通道 -- dbus_message_new_method_call(),注意,在申请远程调用通道的时候,需要填写服务器名,本次调用的接口名,和本次调用名(方法名)。压入本次调用的参数 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic(),实际上是申请了一个首地址,我们就是把我们真正要传的参数,往这个首地址里面送(送完之后一般都会判断是否内存越界了)。然后就是启动发送调用并释放发送相关的消息结构 -- dbus_connection_send_with_reply()。这个启动函数中带有一个句柄。我们马上会阻塞等待这个句柄给我们带回总线上回传的消息。当这个句柄回传消息之后,我们从消息结构中分离出参数。用dbus提供的函数提取参数的类型和参数 -- dbus_message_iter_init(); dbus_message_iter_next(); dbus_message_iter_get_arg_type(); dbus_message_iter_get_basic()。也就达成了我们进行本次远程调用的目的了。
 

2.3发送信号的流程

 建立一个dbus连接之后,为这个dbus连接起名,建立一个发送信号的通道,注意,在建立通道的函数中,需要我们填写该信号的接口名和信号名 -- dbus_message_new_signal()。然后我们把信号对应的相关参数压进去 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic()。然后就可以启动发送了 -- dbus_connection_send(); dbus_connection_flush。

2.4信号接收流程

建立一个dbus连接之后,为这个dbus连接起名,为我们将要进行的消息循环添加匹配条件(就是通过信号名和信号接口名来进行匹配控制的) -- dbus_bus_add_match()。我们进入等待循环后,只需要对信号名,信号接口名进行判断就可以分别处理各种信号了。在各个处理分支上。我们可以分离出消息中的参数。对参数类型进行判断和其他的处理。
 

3. 一个C语言的示例代码

网上大部分代码都是基于dbus的一个封装库libdbus做的,以及使用glib,gtk的事件循环;为了减少库的依赖,直接使用C语言调用dbus的底层函数编写一个远程调用的示例代码,代码很简单,没使用GObject等一些复杂的库。

远程调用的服务器代码,用于监控,代码如下:

#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
{
   DBusMessage* reply;
   DBusMessageIter args;
   bool stat = true;
   dbus_uint32_t level = 21614;
   dbus_uint32_t serial = 0;
   char* param = "";

   // read the arguments
   if (!dbus_message_iter_init(msg, &args))
      fprintf(stderr, "Message has no arguments!\n"); 
   else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) 
      fprintf(stderr, "Argument is not string!\n"); 
   else 
      dbus_message_iter_get_basic(&args, ¶m);

   printf("Method called with %s\n", param);

   // create a reply from the message
   reply = dbus_message_new_method_return(msg);

   // add the arguments to the reply
   dbus_message_iter_init_append(reply, &args);
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) { 
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) { 
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }

   // send the reply && flush the connection
   if (!dbus_connection_send(conn, reply, &serial)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }
   dbus_connection_flush(conn);

   // free the reply
   dbus_message_unref(reply);
}


static void 
reply_to_Introspect(DBusMessage* msg, DBusConnection* conn)
{
	/*反馈的消息*/
	char *xml = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
	"<node>\n"
	"  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
	"    <method name=\"Introspect\">\n"
	"      <arg name=\"introspection_xml\" direction=\"out\" type=\"s\"/>\n"
	"    </method>\n  </interface>\n"
	"  <interface name=\"test.method.Type\">\n"
	"    <method name=\"Method\">\n"
	"      <arg name=\"level\" direction=\"out\" type=\"i\"/>\n"
	"      <arg name=\"serial\" direction=\"out\" type=\"i\"/>\n"
	"    </method>\n"
	"  </interface>\n"
	"</node>\n";
	DBusMessage* reply;
   DBusMessageIter args;
   bool stat = true;
   
   // create a reply from the message
   reply = dbus_message_new_method_return(msg);
   // add the arguments to the reply
   dbus_message_iter_init_append(reply, &args);
   
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &xml)) { 
      printf ("Dbus Error: append args error\n");
      dbus_message_unref(reply);
      return;
   }
   // send the reply && flush the connection
   if (!dbus_connection_send(conn, reply, NULL)) {
      printf ("Dbus Error: send error\n");
      dbus_message_unref(reply);
      return;
   }
   dbus_connection_flush(conn);
   // free the reply
   dbus_message_unref(reply);
}

/**
* Server that exposes a method call and waits for it to be called
*/
void listen() 
{
   DBusMessage* msg;
   DBusMessage* reply;
   DBusMessageIter args;
   DBusConnection* conn;
   DBusError err;
   int ret;
   char* param;

   printf("Listening for method calls\n");

   // initialise the error
   dbus_error_init(&err);
   
   // connect to the bus and check for errors
   conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Connection Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (NULL == conn) {
      fprintf(stderr, "Connection Null\n"); 
      exit(1); 
   }
   
   // request our name on the bus and check for errors
   ret = dbus_bus_request_name(conn, "test.method.server", 
                               DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err);
   }
   if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 
      fprintf(stderr, "Not Primary Owner (%d)\n", ret);
      exit(1); 
   }

   // loop, testing for new messages
   while (true) {
      // non blocking read of the next available message
      dbus_connection_read_write(conn, 0);
      msg = dbus_connection_pop_message(conn);

      // loop again if we haven't got a message
      if (NULL == msg) { 
         sleep(1); 
         continue; 
      }
      
      // check this is a method call for the right interface & method
      if (dbus_message_is_method_call(msg, "test.method.Type", "Method")) 
         reply_to_method_call(msg, conn);
      /*实现反射接口*/
      if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) 
	 reply_to_Introspect(msg, conn);
      // free the message
      dbus_message_unref(msg);
   }
}




int main(int argc, char** argv)
{

   listen();
   return 0;
} 

代码中很关键的一个地方是一个标准接口的实现,该接口虽说无实际意义,仅仅是反射出该session的接口信息,包含各个接口信息和信号信息,但是该信息在python版的dbus中调用很重要,否则python的调用会失败。

编译命令如下

gcc -o main main.c `pkg-config --cflags --libs dbus-1`

可以用d-feet测试一下:

用dbus-send测试命令如下:

dbus-send --session --type=method_call --print-reply --dest=test.method.server / test.method.Type.Method

 

客户端代码(及远程调用的代码):

#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
/**  
 * Call a method on a remote object  
 */  
void query(char* param)    
{   
   DBusMessage* msg;   
   DBusMessageIter args;   
   DBusConnection* conn;   
   DBusError err;   
   DBusPendingCall* pending;   
   int ret;   
   bool stat;   
   dbus_uint32_t level;   
  
   printf("Calling remote method with %s\n", param);   
  
   // initialiset the errors   
   dbus_error_init(&err);   
  
   // connect to the system bus and check for errors   
   conn = dbus_bus_get(DBUS_BUS_SESSION, &err);   
   if (dbus_error_is_set(&err)) {    
      fprintf(stderr, "Connection Error (%s)\n", err.message);    
      dbus_error_free(&err);   
   }   
   if (NULL == conn) {    
      exit(1);    
   }   
  
   // request our name on the bus   
   ret = dbus_bus_request_name(conn, "test.method.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);   
   if (dbus_error_is_set(&err)) {    
      fprintf(stderr, "Name Error (%s)\n", err.message);    
      dbus_error_free(&err);   
   }   
   if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {    
      exit(1);   
   }   
  
   // create a new method call and check for errors   
   msg = dbus_message_new_method_call("test.method.server", // target for the method call   
                                      "/test/method/Object", // object to call on   
                                      "test.method.Type", // interface to call on   
                                      "Method"); // method name   
   if (NULL == msg) {    
      fprintf(stderr, "Message Null\n");   
      exit(1);   
   }   
  
   // append arguments   
   dbus_message_iter_init_append(msg, &args);   
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m)) {   
      fprintf(stderr, "Out Of Memory!\n");    
      exit(1);   
   }   
      
   // send message and get a handle for a reply   
   if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout   
      fprintf(stderr, "Out Of Memory!\n");    
      exit(1);   
   }   
   if (NULL == pending) {    
      fprintf(stderr, "Pending Call Null\n");    
      exit(1);    
   }   
   dbus_connection_flush(conn);   
      
   printf("Request Sent\n");   
      
   // free message   
   dbus_message_unref(msg);   
      
   // block until we recieve a reply   
   dbus_pending_call_block(pending);   
  
   // get the reply message   
   msg = dbus_pending_call_steal_reply(pending);   
   if (NULL == msg) {   
      fprintf(stderr, "Reply Null\n");    
      exit(1);    
   }   
   // free the pending message handle   
   dbus_pending_call_unref(pending);   
  
   // read the parameters   
   if (!dbus_message_iter_init(msg, &args))   
      fprintf(stderr, "Message has no arguments!\n");    
   else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args))    
      fprintf(stderr, "Argument is not boolean!\n");    
   else  
      dbus_message_iter_get_basic(&args, &stat);   
  
   if (!dbus_message_iter_next(&args))   
      fprintf(stderr, "Message has too few arguments!\n");    
   else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))    
      fprintf(stderr, "Argument is not int!\n");    
   else  
      dbus_message_iter_get_basic(&args, &level);   
  
   printf("Got Reply: %d, %d\n", stat, level);   
      
   // free reply    
   dbus_message_unref(msg);      
}   
  



int main(int argc, char** argv)
{
    char* param = "no param";  
    query(param);
    return 0;
} 

 执行结果:

Calling remote method with no param
Request Sent
Got Reply: 1, 21614
 

4.Pthon调用dbus

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import dbus
bus = dbus.SessionBus()
bus_obj = bus.get_object('test.method.server', '/')

interface = dbus.Interface(bus_obj, 'test.method.Type')
info = interface.Method()
print info