用boost python加快vc程序开发

爷,独闯天下 提交于 2019-11-30 05:22:39

目录

  • 用标准c接口嵌入python
  • 用boost python嵌入python
  • 用python来实现业务功能

boost python介绍

有两种方式嵌入python:c的方式和boost python的方式。对于c方式,我从来只用它做简单的执行,比如:

PyRun_SimpleString("import sys");
		PyRun_SimpleString(
			(std::string("if not '") + (LPCSTR)pathA + "' in sys.path: \n"
			"    sys.path.append('" + (LPCSTR)pathA + "')\n").c_str());
		PyRun_SimpleString(
			(std::string("if not '") + (LPCSTR)pathA + "\\PyModule' in sys.path: \n"
			"    sys.path.append('" + (LPCSTR)pathA + "\\PyModule')\n").c_str());
第二种方式是通过boost python嵌入python。我基本上都用它。

Boost.Python是著名的c++库Boost的一个组件,它实现了c++和 python 两种功能丰富的优秀的语言环境间的无缝协作。Boost.Python的另外一个优点是,它的设计目标就是让C++程序库可以透明地导出到 Python中去。即在完全不修改原来 C++ 程序的情况下,导出给Python 用。在这种设计理 念下设计出来的 Boost.Python比同类工具支持了给完善的 C++ 特性,能够最大程度地保证不修改原 C++ 程序。

用boost python嵌入python

接下来介绍第二种嵌入python的方式,就是利用boost python来嵌入python。在pyui4win designer中,有一个扫描xml界面配置文件来生成对应python处理类的一个处理就采用了这个方式:

void CUIDesignerView::OnGenerateCode()
{
	TCHAR szFileName[MAX_PATH];
	CString strFilePath=GetDocument()->GetPathName();

	boost::python::handle<>* _module = NULL; // Module handle.
	try
	{
		_module = new boost::python::handle<>(
			PyImport_ImportModule("GenerateCode"));
		int ret = boost::python::call_method(_module->get(), "GeneratePythonCode", std::string(CStringA(strFilePath).GetBuffer()));
		switch (ret)
		{
		case 0:
			MessageBox(_T("成功生成代码"), _T("提示"), MB_ICONINFORMATION);
			break;
		case -1:
			MessageBox(_T("还未实现"), _T("提示"), MB_ICONERROR);
			break;
		default:
			MessageBox(_T("出错啦"), _T("提示"), MB_ICONERROR);
			break;
		}
	}
	catch(boost::python::error_already_set const &)
	{  
		std::string err = parse_python_exception();
		MessageBox(CString(CStringA(err.c_str())), _T("提示"), MB_ICONERROR);
		PyLog().LogText(err.c_str());
		PyErr_Clear();
	}  
	catch (...)
	{
		if (PyErr_Occurred())
		{
			std::string err = parse_python_exception();
			PyLog().LogText(err.c_str());
			PyErr_Clear();
		}
	}

	if (_module)
		delete _module;
}
以上是一个完整的用boost python来嵌入python的处理。 其中,parse_python_exception函数是异常信息提取函数。在pyui4win designer工程中可以找到。

用python来实现业务功能

我们对GenerateCode.py中的代码更感兴趣。看看GenerateCode的代码:先是py文件模板的定义。

codeTemplate ="""
# coding=gbk
__author__ = 'generated by py-ui4win'

import string, os, time

from PyUI import *
from MsgBox import *
from PyFrameBase import *
import UICommon
from CommonUtil import CommonUtils

class {CLASS_NAME}(PyFrameBase):
    def __init__(self):
        super({CLASS_NAME}, self).__init__()
        self.clsName = self.__class__.__name__
        self.skinFileName = self.__class__.__name__ + '.xml'

    # 不要改动
    def GetSkinFile(self):
        return self.skinFileName

    # 不要改动
    def GetWindowClassName(self):
        return self.clsName

    # 退出处理
    def OnExit(self, sendor, wParam, lParam):
        self.ExitApp()

    # 准备显示前的处理
    def OnPrepare(self, sendor, wParam, lParam):
{ON_PREPARE}
    # 界面事件处理
    def OnNotify(self, sendor, sType, wParam, lParam):
        # 用户点击事件
        if sType == DUI_MSGTYPE_CLICK:
{ON_CLICK}
        # 用户选择事件
        if sType == DUI_MSGTYPE_ITEMSELECT:
{ON_ITEMSELECT}
"""
以上定义的是代码生成模板,用"""的字符串语法要比c++清晰,而且比c++简单多了。如果用c++来定义,里面要写一堆 \n了和"号。

以下是根据xml界面文件来生成对应py文件的处理过程。主要在GenerateCode里。用python写起来真的是很舒服。

class GenerateCode():
    def __init__(self):
        self.code = ''

    def GenerateCode(self, skinXmlPath):
        self.skinXmlPath = skinXmlPath
        if not os.path.isfile(skinXmlPath):
            return -2

        # 分析xml皮肤
        tree = ET.ElementTree(file=skinXmlPath)
        prepare_code = ''
        click_code = ''
        itemselect_code = ''
        for ctltag in ['Control', 'Label', 'Button', 'Option', 'Edit', 'RichEdit','Combo','Text','CheckBox', \
                       'Progress', 'Animation', 'Container', 'HorizontalLayout', 'VerticalLayout', 'TabLayout', 'List', \
                       'WebBrowser']:
            for elem in tree.iter(tag=ctltag):
                if elem.attrib.has_key('name'):
                    #print elem.tag, elem.attrib
                    # OnPrepare
                    prepare_code += '        self.%s = self.PyFind%s("%s")'%(elem.attrib['name'], ctltag, elem.attrib['name']) + os.linesep
                    # DUI_MSGTYPE_CLICK
                    if ctltag in ['Button', 'Option', 'CheckBox']:
                        click_code += '            elif sendor == "%s":'%elem.attrib['name'] + os.linesep
                        click_code += '                pass' + os.linesep
                    # DUI_MSGTYPE_ITEMSELECT
                    if ctltag in ['Combo', 'List']:
                        itemselect_code += '            elif sendor == "%s":'%elem.attrib['name'] + os.linesep
                        itemselect_code += '                pass' + os.linesep

        click_code = click_code.replace('elif', 'if', 1)
        itemselect_code = itemselect_code.replace('elif', 'if', 1)

        # 组合代码
        if os.path.basename(skinXmlPath) == 'MainFrame.xml':
            self.saveFile = os.path.dirname(skinXmlPath) + '\\' + 'PyMain.py' # 要保持为PyMain.py文件
        else:
            self.saveFile = skinXmlPath.replace('.xml','.py')

        self.codeTemp = codeTemplate.replace('\n', '\r\n')
        self.code = self.codeTemp.format(\
            CLASS_NAME = os.path.basename(skinXmlPath).split('.')[0],\
            ON_PREPARE = prepare_code,\
            ON_CLICK = click_code if click_code != '' else '            pass',\
            ON_ITEMSELECT = itemselect_code if itemselect_code != '' else '            pass'\
        )

        #写py文件
        outfile = open(self.saveFile, 'wb')
        outfile.write(self.code)
        outfile.close()

        #打开文件
        shell32 = ctypes.windll.LoadLibrary("shell32.dll");
        shell32.ShellExecuteA(None,'open', 'notepad',self.saveFile,'',1);
        return 0
可以看出,用python开发程序的确很爽。如果是用c++来实现这个功能, 光是定义这些个list和set就很琐碎,而且很没劲。

以下是测试函数

def GeneratePythonCode( skinXmlPath):
    return GenerateCode().GenerateCode(skinXmlPath)

if __name__ == '__main__':
    GeneratePythonCode(r'f:\pyui4win\pyui4win\Demo3\skin\MainFrame.xml')
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!