URN Logo
UNIX Resources » Linux » China Linux Forum » Python 编 程 » 19 » [精华] 在windows上扩展python(2.1)---一个实例
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.net
  业界新闻与评论
  自由软件杂谈
  IT 人生
  Linux软件快递
  翻译作坊
  Linux图书与评论
  GNU Emacs/XEmacs
  Linux 中文环境和中文化
  Linux桌面与办公软件
  Linux 多媒体与娱乐版
  自由之窗Mozilla
  笔记本电脑上的Linux
  Gentoo
  Debian 一族
  网络管理技术
  Linux 安装与入门
  WEB服务器和FTP服务器
  域名服务器和邮件服务器
  Linux防火墙和代理服务器应用
  文件及打印服务器
  技术培训与认证
  Linux内核技术
  Linux 嵌入技术
  Linux设备驱动程序
  Linux 集群技术
  LINUX平台数据库
  系统和网络安全
  CPU 与 编译器
  系统计算研究所专栏
  Linux下的GUI软件开发
  C/C++编程版
  PHP 技 术
  Java&jsp技术
  Shell编程技术
  Perl 编 程
  Python 编 程
  XML/Web Service 技术
  永远的Unix
  FreeBSD世界
   
[精华] 在windows上扩展python(2.1)---一个实例
 
 
 
Subject: [精华] 在windows上扩展python(2.1)---一个实例
Author: rings    Posted: 2004-04-13 21:40    Length: 8,665 byte(s)
[Original] [Print] [Top]
在windows上扩展python(2.1)---一个实例

在win32编程中,我们经常使用timer来定时的出发一些事件。 SetTimer来创建一个定时器, 他的原型是:

UINT_PTR SetTimer(
HWND hWnd, // handle to window
UINT_PTR nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // timer procedure
);

lpTimerFunc就是定时器的回调函数。在第二篇的时候,我们也可以在python中设置回调函数。python提供这个方法
主要是用来扩展c中的一些实现。在python win32的扩展模块中。我们可以看到他的具体使用。他对timer的几个win32 API的包装
都写在timermodule.cpp(请看附件)

在这个文件中,他的整个做法和我们上两节讲过的是一样的。

extern"C" __declspec(dllexport) void
inittimer(void)
{
PyObject *dict, *module;
module = Py_InitModule("timer", timer_functions);
if (!module) /* Eeek - some serious error! */
return;
dict = PyModule_GetDict(module);
if (!dict) return; /* Another serious error!*/
timer_module_error = PyString_FromString("timer error");
PyDict_SetItemString(dict, "error", timer_module_error);
PyDict_SetItemString(dict, "__version__", PyString_FromString("0.2"));
timer_id_callback_map = PyDict_New();
}

这个是他的初始化函数。他的这个module的名字是timer。这个函数也是别导出的,所以需要__declspec(dllexport)。
在看这个映射表:
// List of functions exported by this module
static struct PyMethodDef timer_functions[] = {
{"set_timer", py_timer_set_timer, 1},
{"kill_timer", py_timer_kill_timer, 1},
#ifdef _DEBUG
{"_id_timer_map", py_timer_timer_map, 1},
#endif
{NULL, NULL}
};


我们可以看到,一共映射了3个函数,_id_timer_map是为了调试的。我们暂且不管。 其他两个是set_timer和kill_timer。
我们可以在python的timer模块里看到这两个函数。过会我们会来显示他们。
set_timer对应的c函数是py_timer_set_timer:

static PyObject *
py_timer_set_timer (PyObject * self, PyObject * args)
{
PyObject *callback;
PyObject * py_timer_id;
int elapse;
UINT timer_id;

if (!PyArg_ParseTuple (args, "iO", &elapse, &callback)) {
return NULL;
}

// make sure the callback is a valid callable object
if (!PyCallable_Check (callback)) {
PyErr_SetString (timer_module_error, "argument must be a callable object");
return NULL;
}

// create the win32 timer
Py_BEGIN_ALLOW_THREADS;
timer_id = ::SetTimer (NULL, 0, (UINT) elapse, (TIMERPROC) py_win32_timer_callback);
Py_END_ALLOW_THREADS;

if (!timer_id) {
PyErr_SetString (timer_module_error, "win32 SetTimer() failed");
return NULL;
}

py_timer_id = PyInt_FromLong((long) timer_id);
if (!py_timer_id)
return NULL;

// associate the timer id with the given callback function
if (PyObject_SetItem (timer_id_callback_map,
py_timer_id,
callback) == -1) {
::KillTimer (NULL, timer_id);
Py_DECREF(py_timer_id);
PyErr_SetString (timer_module_error,
"internal error, couldn't set timer id callback item");
return NULL;
}
// everything went ok.
return py_timer_id;
}
大部分的结构我们都已经讲过了,看这行:
PyObject_SetItem (timer_id_callback_map, py_timer_id, callback)
他将一个timerid和一个python用户设置的函数关联起来。并且把他存储到一个map中去, 这个map就是python 中的dict。
比如, map[timerid] = callback

另外, 我们需要注意这行代码:

timer_id = ::SetTimer (NULL, 0, (UINT) elapse, (TIMERPROC) py_win32_timer_callback);
这个是win32 API的调用,py_win32_timer_callback是定时器的回调函数。他的定义是这样的:

VOID CALLBACK
py_win32_timer_callback (HWND hwnd, UINT msg, UINT event, DWORD time)
{
// do we have a valid callback dictionary?

if (timer_id_callback_map) {
CEnterLeavePython _celp;
PyObject * py_event = Py_BuildValue ("i", (int) event);

// is this timer id recognized?
PyObject * callback_function =
PyDict_GetItem (timer_id_callback_map, py_event);

// call the user's function
if (callback_function) {
PyObject * callback_args = Py_BuildValue ("(il)", (int) event, (long) time);
PyObject * result =
PyEval_CallObject (callback_function, callback_args);

if (!result) {
// Is this necessary, or will python already have flagged
// an exception? Can we even catch exceptions here?
PyErr_Print();
}

// everything's ok, return
Py_XDECREF(callback_args);
Py_XDECREF(result);
Py_DECREF (py_event);
return;
}
// invalid key or callback: remove the key and kill the timer.
PyDict_DelItem(timer_id_callback_map, py_event);
Py_DECREF (py_event);
::KillTimer (NULL, event);
return;
} else {
// the id/callback map is NULL
::KillTimer (NULL, event);
}
}
他在一个callback map中根据timer id找到对应的回调函数, PyObject * py_event = Py_BuildValue ("i", (int) event);这句话
就是得到timer id。 他得到的就是在py_timer_set_timer函数里python传递过来的callback。 我们已经把他存储在map中了。

然后调用这个函数,PyEval_CallObject (callback_function, callback_args);在这里, 参数, callback_function就是我们找到的那个
回调函数。PyEval_CallObject我们已经讲过了。

py_timer_kill_timer 很简单:
static PyObject *
py_timer_kill_timer (PyObject * self, PyObject * args)
{
PyObject * py_timer_id;

if (!PyArg_ParseTuple (args, "O", &py_timer_id)) {
return NULL;
} else if (timer_id_callback_map) {
if (0 != PyDict_DelItem (timer_id_callback_map, py_timer_id)) {
return NULL;
}
}
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = ::KillTimer (NULL, (int) PyInt_AsLong (py_timer_id));
Py_END_ALLOW_THREADS;
return Py_BuildValue ("i", rc);
}
他先得到这个timer id,然后从map里把他对应的这一项删除。PyDict_DelItem (timer_id_callback_map, py_timer_id)。
然后真正调用win32 API KillTimer.

在python中做测试:

>>> import timer
>>> dir(timer)
['__doc__', '__file__', '__name__', '__version__', 'error', 'kill_timer', 'set_timer']

>>> import time
>>> def testtimer(id, timeinterval):
... print time.localtime()
...
>>> def starttimer():
... start_time = time.time()
... timerid = timer.set_timer(5000, testtimer)
... print timerid
...

我们设置一个时间间隔5秒的定时器, 他的定时器回调函数是testtimer。 在c中,他将把testtimer, 和timerid
放入到一个map中去。

>>> starttimer()
23557

23557就是timerid

>>> (2004, 4, 13, 20, 42, 8, 1, 104, 0)
(2004, 4, 13, 20, 42, 13, 1, 104, 0)
>>> (2004, 4, 13, 20, 42, 18, 1, 104, 0)
(2004, 4, 13, 20, 42, 23, 1, 104, 0)
(2004, 4, 13, 20, 42, 28, 1, 104, 0)
(2004, 4, 13, 20, 42, 33, 1, 104, 0)


>>> timer.kill_timer(23557)
1

返回1表示成功kill掉timer了。



--
Attached file: 485739-timermodule.txt
[Original] [Print] [Top]
Subject: Re: 在windows上扩展python(2.1)---一个实例
Author: xichen    Posted: 2004-07-06 08:53    Length: 34 byte(s)
[Original] [Print] [Top]
这个程序怎么编译啊,能将清楚点吗》
----
[Original] [Print] [Top]
Subject: Re: 在windows上扩展python(2.1)---一个实例
Author: rings    Posted: 2004-07-06 09:37    Length: 48 byte(s)
[Original] [Print] [Top]
你可以找到这个文章的第一篇。有一个可以编译的例子
[Original] [Print] [Top]
« Previous thread
py2exe问题
Python 编 程
19
Next thread »
[精华] UTF-8编码的文件检测函数
     

Copyright © 2007 UNIX Resources Network, All Rights Reserved.      About URN | Privacy & Legal | Help | Contact us
备案序号: 京ICP备05006143    webmaster: webmaster@unixresources.net
This page created on 2008-07-17 04:11:41, cost 0.043406963348389 ms.