安装python
后,会有一个chm
格式的python
手册。要搞明白如何让python
调用C/C++
代码(
也就是写python
的 extension)
,你需要征服手册中的<<Extending && embedding>>
厚厚的一章。在昨天花了一个小时看地头晕脑胀,仍然不知道如何写python
的extension
后,查阅了一些其他 书籍,最终在<<Python Programming On Win32>>
书中找到了教程。
下面记录一下如何在visual studio 2005
中,写一段C/C++
的MessageBox
代码,然后提供后python
调用,最后的结果当然是显示一个MessageBox.
1.
首先要明白的是,所谓的python
扩展(也就是你提供给python
的c/c++
代码,不一定是c/c++
代码,可以是其他语言写的代码)
是一个 dll,
并且这个dll
放在本机python
安装目录下的DLLs
目录下(譬如我机器上的路径是:F:/Program Files/Python25/DLLs)
,假如我们接下来要写的扩展module
名为mb,python
调用的代码为:
import mb
mb.showMsg("Python's really amazing, I kindda love it!")
python
怎么找到我们的mb
模块呢?就是上面说的,我们要生成一个mb.dll
,然后拷贝到Dlls
目录下面,为了区别普通的dll
和python
专用扩展的dll,
我们的 mb.dll
修改成mb.pyd(python dll)
2.
搭建环境,我们要使用python
提供的c
头文件和lib
库来进行扩展的开发。
在vs 2005
下点击菜单 "
工具"->"
选项",
打开选项对话框,选择"
项目和解决方案->VC++
目录",
然后在右边"
显示以下内容的目录"
得comboBox
上选择"
包含文件”
,添加python
的include
目录(
我的机器上是"F:/Program Files/Python25/include"),
然后选择库文件,
添加python
的libs
目录(
我的机器上是"F:/Program Files/Python25/libs")
。
既然扩展是一个dll,
接下来我们要建立一个“
动态链接库”
工程,然后开始写代码:
#include <python.h> //python.h
是包含python
一些定义的头文件,在python
的include
目录下
/*
我的python
版本是2.5,
因为安装python
后它没提供debug
下的lib
库文件,因此你必须生成release
版的dll
,
想要生成dll
版本的,你要到python
官网上自己去下载python
源代码,
当然你可以继续生成release
版本的dll,
但dll
中包含调试信息
*/
#pragma comment(lib, "python25.lib")
//
先不管
static PyObject* mb_showMsg(PyObject* self, PyObject *args);
/*
如果你的扩展是mb,
那么必须实现一个initmb
函数,并且从dll
中导出这个函数,但我们在python
中调用import mb
时,python
会去dll
里去调用
initmb
函数,这个函数告诉python
我们有些什么函数,
该怎么告诉python
我们有一个showMsg
函数呢?下面详解
*/
//
必须extern "C"
下,这样不会在C++
编译器里不会更改掉导出的函数名字,我第一次就犯了这样的错误
extern "C" __declspec(dllexport) void initmb()
{
/*
当调用mb.showMsg("Python's really amazing, I kindda love it!")
时, 相当于你告诉python
我有一个showMsg
函数,我们怎么告诉python
去调用我们dll
里的mb_showMsg
函数呢?技巧就是下面的方式, 定义一个字典数据结构,key => showMsg, value =>mb_showMsg,METH_VARARGS
是函数调用方式,仔细查手册吧
*/
static PyMethodDef mbMethods[] = {
{"showMsg", mb_showMsg, METH_VARARGS},
{NULL, NULL, NULL} /*sentinel
,哨兵,用来标识结束*/
};
//
告诉python
我们的模块名叫mb,
模块包含的函数都在mbMethods
字典里
PyObject *m = Py_InitModule("mb", mbMethods);
}
/*
接下来实现核心功能showMsg
*/
//
第一个self
参数我们用不着,具体查手册,第二个参数是python
传给我们的参数,
它是一个python
的参数tuple
static PyObject* mb_showMsg(PyObject* self, PyObject *args)
{
//
我们的showMsg
函数需要的是一个字符串参数
const char* msg = NULL;
/*
调用特殊参数解码python
传递给我们的参数,s
是string,
我们传递接收参数的变量地址,
如果你的功能函数需要两个参数,在PyArg_parseTuple
后面继续添加接受参数的变量地址,
这个函数的原型是类似printf
的不定参数的形式
PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...);
*/
if (!PyArg_ParseTuple(args, "s", &msg))
return NULL;
//
调用MB
int r = ::MessageBox(NULL, "hello", "Caption:Form C module", MB_ICONINFORMATION | MB_OK);
//
返回值
return Py_BuildValue("i", r);
}
将上面这段混杂着大量注释的代码拷贝到你的编辑器里,然后编译生成mb.dll,
修改后缀成mb.pyd,
然后拷贝到python
的DLLs
目录下,打开idle(python
的交互程序),
写入代码:
import mb
mb.showMsg("Python's really amazing, I kindda love it!")
可以看到弹出来一个MessageBox
。
python调用C和C++代码
最新推荐文章于 2025-05-27 16:22:06 发布