征服Python:语言基础与典型应用

 
征服Python:语言基础与典型应用 --8.1.2 程序详解

一般的Python扩展程序中应包含以下3部分内容。

1.初始化函数

初始化函数是必须的,用于Python解释器对模块进行正确的初始化。初始化函数的函数名必须以init开头,并加上模块的名字。例如上节中初始化函数的函数名为“initmyext”,其中“myext”为模块名。函数“initmyext”代码如下所示。

PyMODINIT_FUNC initmyext()

{

    PyObject *mod;

    mod = Py_InitModule("myext",myextMethods);

}

其中PyMODINIT_FUNC为Python头文件中定义的宏,在Windows下其相当于_declspec(dllexport) void,即将initmyext声明为void型,并且将其设为DLL文件的导出函数。初始化函数中的Py_InitModule函数,其函数原型如下所示。

PyObject* Py_InitModule( char *name, PyMethodDef *methods)

其参数含义如下。

·     name:模块名。

·     methods:方法列表。

2.方法列表

方法列表中包含了Python扩展中的所有可以调用的函数方法。方法列表应该被声明为“static PyMethodDef”。上一节实例中的方法列表如下所示。

static PyMethodDef myextMethods[] =

{

    {"show", show, METH_VARARGS,"show a messagebox"},

    {NULL,NULL}

};

每一个函数方法对应于方法列表中的由大括号包围的一项。大括号中由4部分组成,模块中的方法名,与之对应的Python扩展中的函数名、函数调用方法,以及方法描述。其中函数调用方法应该为“METH_VARARGS”或者“METH_VARARGS | METH_KEYWORDS”。也可以将函数调用方法设置为0。方法列表应该以由两个NULL组成的一项来表示结束。

3.函数实现

方法列表中包含了模块中方法对应的C语言函数实现。在Python扩展中所有的函数都应该被声明为“PyObject *”型,每个函数都应当含有两个“PyObject *”型的参数。在上一节的实例中,模块方法的实现函数如下所示。

PyObject *show(PyObject *self, PyObject *args)

{

    char *message;

    const char *title = NULL;

    HWND hwnd = NULL;

    int r;

    if (!PyArg_ParseTuple(args, "iss", &hwnd, &message, &title))

        return NULL;

    r = MessageBox(hwnd,message, title, MB_OK);

    return Py_BuildValue("i", r);

}

其中参数self只有在函数为Python的内置方法时才被使用,其余情况下self为一个空指针。参数args为在Python中向方法传递的参数。如果在方法列表中指定的函数调用方法为“METH_VARARGS”,则在函数中使用PyArg_ParseTuple处理参数。如果在方法列表中指定的函数调用方法为“METH_VARARGS | METH_KEYWORDS”,则应该使用PyArg_ParseTupleAndKeywords处理参数。其中PyArg_ParseTuple的函数原型如下所示。

int PyArg_ParseTuple( PyObject *args, const char *format, ...)

其参数含义如下。

·     args:传递的参数。

·     format:参数类型描述。

PyArg_ParseTuple为可变参数函数,其后的参数即在函数中接受Python中传递参数的变量。在上述的show函数中,要使用3个参数,分别为hwnd、message、title。在PyArg_ParseTuple中将其作为参数,使用“&”向hwnd、message、title传递值,即将Python向show方法传递的参数依次赋值给hwnd、message、title。

PyArg_ParseTuple函数中的format参数指定了其后参数的类型,在show函数中format参数为“iss”表示hwnd为整型,message和title为字符串。常见的指定参数类型的字符如表8-1所示。

表8-1                                                 常见的指定参数类型的字符

格式化字符

C数据类型

Python类型

s

char*

字符串

s#

char*, int

字符串及长度

z

char*

与s相同,但可以为NULL

续表

格式化字符

C数据类型

Python类型

z#

char*, int

与s#相同,但可以为NULL

i

int

长整型

l

long int

长整型

c

char

单个字符的字符串

f

float

双精度型

d

double

双精度型

8.1.3 在Python扩展中使用MFC

在Windows下使用MFC可以方便地进行GUI编程。MFC对基本的SDK API函数进行了封装,使用更为简便。在PythonWin中提供了部分MFC中的函数。在Python扩展中使用MFC与上一节中的例子有不同的地方。此处给出一个在Python扩展中使用MFC创建一个对话框的例子。整个过程如下所示。

(1)单击【File】|【New】命令,弹出创建工程对话框。单击【Projects】标签,选择左侧列表中的【MFC AppWizard (dll)】项,在【Project name】文本框中输入工程名“UseMFC”,如图8-17所示。

(2)单击【OK】按钮,弹出如图8-18所示的工程设置对话框。选中【Regular DLL using shared MFC DLL】单选框,使用动态链接方式。该方式需要MFC DLL的支持,如果选中【Regular DLL with MFC statically linked】单选框,则使用静态链接的方式,这样会增大生成的Python扩展的体积。

   

           图8-17 创建工程对话框                         图8-18 设置工程类型对话框

(3)单击【Finish】按钮,弹出如图8-19所示的确认对话框。单击【OK】按钮完成工程创建。

(4)单击【Insert】|【Resource】命令,弹出添加资源对话框,选择左侧列表中的【Dialog】项,如图8-20所示。

   

        图8-19 工程信息确认对话框                           图8-20 添加资源对话框

(5)单击【New】按钮将在工程中新建一个对话框。向对话框中添加Edit控件和Static Text控件,将其修改为如图8-21所示的形式。

(6)在创建的对话框上右击,选择【ClassWizard】命令,弹出如图8-22所示的添加类对话框。

   

             图8-21 创建对话框                          图8-22 为对话框添加类

(7)单击【OK】按钮为对话框添加一个新类,在弹出的添加类对话框中的【Name】文本框中将类命名为“CInput”,其余按照默认选项,如图8-23所示。

(8)右击创建的对话框,选择【ClassWizard】命令,弹出如图8-24所示的对话框。

(9)单击【Member Variables】标签,选中【IDC_EDIT1】项,单击【Add Variable】按钮,弹出如图8-25所示的对话框。

   

              图8-23 输入类名                              图8-24 MFC类向导对话框

(10)在【Member variable name】文本框中输入“m_input”为控件IDC_EDIT1添加变量,即获取文本框中输入的字符串,如图8-26所示。单击【OK】按钮,完成添加变量。

图8-25 添加变量对话框

(11)打开UseMFC.cpp文件,将如下文件添加到其中。

#include "Input.h"

#include <Python.h>

然后将如下所示代码添加到UseMFC.cpp文件中。

PyObject *show(PyObject *self, PyObject *args)

{

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    CInput dia;

    dia.DoModal();

    return Py_BuildValue("s", dia.m_input);

}

static PyMethodDef UseMFCMethods[] =

{

    {"show", show, METH_VARARGS,"show a messagebox"},

   {NULL,NULL}

};

extern "C" void initUseMFC()

{

    PyObject *mod;

    mod = Py_InitModule("UseMFC",UseMFCMethods);

}

(12)打开UseMFC.def文件,将初始化函数添加到UseMFC.def文件中。def文件是用来告诉链接器DLL文件的导出函数的,相当于使用PyMODINIT_FUNC声明初始化函数。UseMFC.def文件内容如下所示。

; UseMFC.def : Declares the module parameters for the DLL.

LIBRARY      "UseMFC"

DESCRIPTION 'UseMFC Windows Dynamic Link Library'

EXPORTS

    ; Explicit exports can go here

    initUseMFC

(13)按照8.1.1节中创建工程的第(6)~(10)步操作,完成Python扩展的编译。

(14)编写如下所示的UseMFC.py,调用编译好的UseMFC模块。

# -*- coding:utf-8 -*-

# file: UseMFC.py

#

import UseMFC                   # 导入UseMFC模块

input = UseMFC.show()           # 调用show函数

print '刚才输入的是:'

print input

(15)运行脚本后,在文本框中输入“Hi,Python and MFC!”,如图8-27所示。单击【OK】按钮后,如图8-28所示。

   

             图8-26 设置变量名                        图8-27 脚本运行弹出对话框

图8-28 脚本获得文本框中的文本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值