1. 怎样让python脚本与C++程序互相调用

二、Python调用C/C++

1、Python调用C动态链接库

Python调用C库比较简单,不经过任何封装打包成so,再使用python的ctypes调用即可。
(1)C语言文件:pycall.c

[html] view plain
/***gcc -o libpycall.so -shared -fPIC pycall.c*/
#include <stdio.h>
#include <stdlib.h>
int foo(int a, int b)
{
printf("you input %d and %d\n", a, b);
return a+b;
}
(2)gcc编译生成动态库libpycall.so:gcc -o libpycall.so -shared -fPIC pycall.c。使用g++编译生成C动态库的代码中的函数或者方法时,需要使用extern "C"来进行编译。
(3)Python调用动态库的文件:pycall.py

[html] view plain
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libpycall.so")
lib.foo(1, 3)
print '***finish***'
(4)运行结果:

2、Python调用C++(类)动态链接库

需要extern "C"来辅助,也就是说还是只能调用C函数,不能直接调用方法,但是能解析C++方法。不是用extern "C",构建后的动态链接库没有这些函数的符号表。
(1)C++类文件:pycallclass.cpp

[html] view plain
#include <iostream>
using namespace std;

class TestLib
{
public:
void display();
void display(int a);
};
void TestLib::display() {
cout<<"First display"<<endl;
}

void TestLib::display(int a) {
cout<<"Second display:"<<a<<endl;
}
extern "C" {
TestLib obj;
void display() {
obj.display();
}
void display_int() {
obj.display(2);
}
}
(2)g++编译生成动态库libpycall.so:g++ -o libpycallclass.so -shared -fPIC pycallclass.cpp。
(3)Python调用动态库的文件:pycallclass.py

[html] view plain
import ctypes
so = ctypes.cdll.LoadLibrary
lib = so("./libpycallclass.so")
print 'display()'
lib.display()
print 'display(100)'
lib.display_int(100)
(4)运行结果:

3、Python调用C/C++可执行程序
(1)C/C++程序:main.cpp

[html] view plain
#include <iostream>
using namespace std;
int test()
{
int a = 10, b = 5;
return a+b;
}
int main()
{
cout<<"---begin---"<<endl;
int num = test();
cout<<"num="<<num<<endl;
cout<<"---end---"<<endl;
}
(2)编译成二进制可执行文件:g++ -o testmain main.cpp。
(3)Python调用程序:main.py

[html] view plain
import commands
import os
main = "./testmain"
if os.path.exists(main):
rc, out = commands.getstatusoutput(main)
print 'rc = %d, \nout = %s' % (rc, out)

print '*'*10
f = os.popen(main)
data = f.readlines()
f.close()
print data

print '*'*10
os.system(main)
(4)运行结果:

4、扩展Python(C++为Python编写扩展模块)
所有能被整合或导入到其它python脚本的代码,都可以被称为扩展。可以用Python来写扩展,也可以用C和C++之类的编译型的语言来写扩展。Python在设计之初就考虑到要让模块的导入机制足够抽象。抽象到让使用模块的代码无法了解到模块的具体实现细节。Python的可扩展性具有的优点:方便为语言增加新功能、具有可定制性、代码可以实现复用等。
为 Python 创建扩展需要三个主要的步骤:创建应用程序代码、利用样板来包装代码和编译与测试。
(1)创建应用程序代码

[html] view plain
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int fac(int n)
{
if (n < 2) return(1); /* 0! == 1! == 1 */
return (n)*fac(n-1); /* n! == n*(n-1)! */
}

char *reverse(char *s)
{
register char t, /* tmp */
*p = s, /* fwd */
*q = (s + (strlen(s) - 1)); /* bwd */

while (p < q) /* if p < q */
{
t = *p; /* swap & move ptrs */
*p++ = *q;
*q-- = t;
}
return(s);
}

int main()
{
char s[BUFSIZ];
printf("4! == %d\n", fac(4));
printf("8! == %d\n", fac(8));
printf("12! == %d\n", fac(12));
strcpy(s, "abcdef");
printf("reversing 'abcdef', we get '%s'\n", \
reverse(s));
strcpy(s, "madam");
printf("reversing 'madam', we get '%s'\n", \
reverse(s));
return 0;
}
上述代码中有两个函数,一个是递归求阶乘的函数fac();另一个reverse()函数实现了一个简单的字符串反转算法,其主要目的是修改传入的字符串,使其内容完全反转,但不需要申请内存后反着复制的方法。
(2)用样板来包装代码
接口的代码被称为“样板”代码,它是应用程序代码与Python解释器之间进行交互所必不可少的一部分。样板主要分为4步:a、包含Python的头文件;b、为每个模块的每一个函数增加一个型如PyObject* Mole_func()的包装函数;c、为每个模块增加一个型如PyMethodDef MoleMethods[]的数组;d、增加模块初始化函数void initMole()。

2. 如何实现 C/C++ 与 Python 的通信

引入Python可以带来更好的可调式性。且如果重负载应用使用C/C++则基本没有性能损失,并可以让工程师把更多精力放在算法优化获得性能优势上。
简单讲Python与C/C++的直接交互就是两种方向:C/C++写扩展模块给Python调用;将Python嵌入C/C++。题主说的是后者。而更方便方式是前者。因为内嵌方式决定了你整个交互部分开发完成之前没法做测试。而扩展模块方式则可以先行用Python快速开发出大部分功能,有需要性能优化的部分逐步优化到C/C++。是更加渐进式的过程。
直接用最基础的方法写扩展模块略有繁杂,适合对细节的控制。题主时间紧迫则可以考虑Cython,可以在较短时间里完成些任务。但更多高级功能的玩法则限制很多。
其他交互方式还有多种,性能就不是那么高了。比如fork()子进程,用管道通信。开独立进程走mmap()交互,甚至是本机或其他机器上走socket。
最后,C++做了很多底层抽象,使得其与其他编程语言的互调用方面麻烦的要死。比较典型的包括类继承,运算符重载,引用,其他还有太多。这些特性使得其他语言调用C++时各种恶心。这不仅仅是对Python,而是对所有语言都是如此。不信试试在C程序里调用一个C++运算符重载过的方法。所以,如非必要,尽量别用C++。用C简单方便的多,而任何用以支持大规模项目的架构用Python就是了。

3. 命令行模式和Python交互模式有什么区别

命令行模式是直接在命令行窗口中运行python的py文件,需要先用文本编辑器编写代码,再内通过命令行模式运行。交容互模式是执行一行就返回一行代码的结果。

1、首先编写一个py文件,然后打开cmd,输入“python 文件路径”就可以执行这个py文件。如下图输入的是“python 1.py”。这种就是命令行模式

4. 如何实现C/C++与Python的通信

这个可以称之为两个软件(进程)之间的通信。

进程间通信主要包括管道, 系统IPC(包括消息内队列容,信号量,共享存储), SOCKET.

比如:你可以共同访问计算机上的一个txt文件
也可以使用socket通信
也可以使用数据库,
等等
都能达到通信的目的

5. 用python 去和c++程序交互,该看哪些知识点

从开始看Python到现在也有半个多月了,前后看了Python核心编程和Dive into
Python两本书。话说半个月看两本,是个人都知道有多囫囵吞枣,这也是因为我暂时没有需求拿这个做大型开发,主要是平时的小程序test用一用。所以

我的策略是,整体浏览,用到时候现查。话说这核心编程第一版太古老了,老在讲2.2之前的东西,我看的翻译电子版,翻译得也不好,很晦涩。看完这个后还有
点云里雾里,看网上人家说DIP好,啄木鸟还有电子文档,就找来看这个。怎么说呢,讲的比核心编程好,但不适合第一次看的初学者。我之所以觉得讲得
好,是因为看核心编程,有些概念还有些模糊,看了这本书就明白不少了。要是初学者上来就看这本,保证不好理解。

下面就是在学习的过程中,在翻阅资料的过程中,总结的一些C和python比较明显的不同之处,有大方向的,也有细节的。肯定没有总结完,比如动态

函数,lambda这些,我都懒得往上写了。实际上,作为两种完全不同的语言,下面这些差异只是冰山一角而已。权当抛砖引玉吧,至少应该对和我有相同研究

兴趣,正在考虑是否学习另一门语言的朋友有点帮助。此文也算是DIP的学习笔记吧。顺带说一句,要是有朋友了解,可以帮忙推荐一下实战性强的Python
教材,语言这东西,不多练手,光比划,是不可能学好的。

学习目的

我的以后的研究方向是嵌入式,显然,C语言是我的主要语言。我不是一个语言爱好者,我以前觉得,对于做研究而不是应用的人来说,了解多门语言,不如

精通一门语言。之所以去看python,主要还是因为python更有利于快速开发一些程序,也是因为现在认识到,研究和应用是不能分离的。个人以为,要
想在计算机工程的竞争中立足,必须懂C语言。因为真正要做高性能编程,
不可能将机器的体系架构抛到脑后让Python虚拟机(或java虚拟机等)帮你搞定所有底层。越来越多的CPU
core,越来越恐怖的内存性能瓶颈,对于上层开发人员来说,无所谓,但是对高性能程序开发人员来说,这些是无法透明的。很多应用,还是自己掌控比较有
效。这些场合中,汇编和C还是不可替代的。但是,光知道C是不够的,掌握一门面向对象语言,相对更高层的语言,不仅对以后的个人发展有利,也会对自己的技
术认识产生帮助。

如果要问对我来说谁更重要,我觉得还是C更重要。C的学习曲线更陡,貌似简单,实际上到处都是陷阱,看上去比较简单低效的程序,也不是学1,2个月

就能搞定的。谈到优化的深层次和难度嘛,需要的功底是按年算的。但是一旦你C语言的基础打好了,对计算机的理解,对其他语言的理解都是大有裨益的。比如,

如果你有C基础,可以说,学过1天python,就能写的出来一些不短的程序。后面的优化也不是什么大不了的算法,都是非常基本的语句换来换去。当然这里
不是说 Python不好,实际上,上层应用,Python比C方便的不是一个层次。

很多人觉得,既然懂C了,那么进一步掌握C++应该是水到渠成,但C++不是C的超集,而我又不喜欢C++的繁琐和巨大,所以才决定看一看Python。我很喜欢Python的优雅与快捷。

语言类型

和C不一样,Python是一种动态类型语言,又是强类型语言。这个分类怎么理解呢?大概是可以按照下列说明来分类的:

静态类型语言

一种在编译期间就确定数据类型的语言。大多数静态类型语言是通过要求在使用任一变量之前声明其数据类型来保证这一点的。Java和 C 是静态类型语言。

动态类型语言

一种在运行期间才去确定数据类型的语言,与静态类型相反。Python 是动态类型的,因为它们确定一个变量的类型是在您第一次给它赋值的时候。

强类型语言

一种总是强制类型定义的语言。Java 和 Python 是强制类型定义的。您有一个整数,如果不明确地进行转换 ,不能将把它当成一个字符串。

弱类型语言

一种类型可以被忽略的语言,与强类型相反。VBScript 是弱类型的。在 VBScript 中,您可以将字符串 ‘12′ 和整数 3 进行连接得到字符串’123′,然后可以把它看成整数 123 ,所有这些都不需要任何的显示转换。

对象机制

具体怎么来理解这个“动态确定变量类型”,就要从Python的Object对象机制说起了。Objects(以下称对象)是Python对于数据

的抽象,Python中所有的数据,都是由对象或者对象之间的关系表示的,函数是对象,字符串是对象,每个东西都是对象的概念。每一个对象都有三种属性:

实体,类型和值。理解实体是理解对象中很重要的一步,实体一旦被创建,那么就一直不会改变,也不会被显式摧毁,同时通常意义来讲,决定对象所支持的操作方

式的类型(type,包括number,string,tuple及其他)也不会改变,改变的只可能是它的值。如果要找一个具体点的说明,实体就相当于对

象在内存中的地址,是本质存在。而类型和值都只是实体的外在呈现。然后Python提供一些接口让使用者和对象交互,比如id()函数用来获得对象实体的
整形表示(实际在这里就是地址),type()函数获取其类型。

这个object机制,就是c所不具备的,主要体现在下面几点:

1 刚才说了,c是一个静态类型语言,我们可以定义int a, char
b等等,但必须是在源代码里面事先规定。比如我们可以在Python里面任意一处直接规定a =
“lk”,这样,a的类型就是string,这是在其赋值的时候才决定的,我们无须在代码中明确写出。而在C里面,我们必须显式规定char *a =
“lk”,也就是人工事先规定好a的类型

2 由于在C中,没有对象这个概念,只有“数据的表示”,比如说,如果有两个int变量a和b,我们想比较大小,可以用a ==
b来判断,但是如果是两个字符串变量a和b,我们就不得不用strcmp来比较了,因为此时,a和b本质上是指向字符串的指针,如果直接还是用==比较,
那比较的实际是指针中存储的值——地址。

在Java中呢,我们通过使用 str1 == str2 可以确定两个字符串变量是否指向同一块物理内存位置,这叫做“对象同一性”。在 Java 中要比较两个字符串值,你要使用 str1.equals(str2)。

然后在Python中,和前两者都不一样,由于对象的引入,我们可以用“is”这个运算符来比较两个对象的实体,和具体对象的type就没有关系
了,比如你的对象是tuple也好,string也好,甚至class也好,都可以用”is”来比较,本质上就是“对象同一性”的比较,和Java中
的==类似,和 C中的pointer比较类似。Python中也有==比较,这个就是值比较了。

3
由于对象机制的引入,让Python的使用非常灵活,比如我们可以用自省方法来查看内存中以对象形式存在的其它模块和函数,获取它们的信息,并对它们进行
操作。用这种方法,你可以定义没有名称的函数,不按函数声明的参数顺序调用函数,甚至引用事先并不知道名称的函数。 这些操作在C中都是不可想象的。

4 还有一个很有意思的细节,就是类型对对象行为的影响是各方面的,比如说,a = 1; b =
1这个语句中,在Python里面引发的,可能是a,b同时指向一个值为1的对象,也可能是分别指向两个值为1的对象。而例如这个语句,c = []; d
= [],那么c和d是肯定指向不同的,新创建的空list的。没完,如果是”c = d =
[]“这个语句呢?此时,c和d又指向了相同的list对象了。这些区别,都是在c中没有的。

最后,我们来说说为什么python慢。主要原因就是function call
overhead比较大。因为所有东西现在都是对象了,contruct 和destroy 花费也大。连1 + 1 都是 function
call,像’12′+’45′ 这样的要 create a third string object, then calls the string
obj’s __add。可想而知,速度如何能快起来?

列表和数组

分析Python中的list和C中的数组总是很有趣的。相信可能一些朋友和一样,初学列表的时候,都是把它当作是数组来学的。最初对于list和数组区别的定性,主要是集中在两点。首先,list可以包含很多不同的数据类型,比如

["this", 1, "is", "an", "array"]

这个List,如果放在C中,其实是一个字符串数组,相当于二维的了。

其次呢,list有很多方法,其本身就是一个对象,这个和C的单纯数组是不同的。对于List的操作很多样,因为有方法也有重载的运算符。也带来一些问题,比如下面这个例子:

加入我们要产生一个多维列表,用下面这个语句

A = [[None] * 2] * 3

结果,A的值会是

[[None, None], [None, None], [None, None]]

初一看没问题,典型的二维数组形式的列表。好,现在我们想修改第一个None的值,用语句

A[0][0] = 5

现在我们再来看看A的值:

[[5, None], [5, None], [5, None]]

发现问题没有?这是因为用 * 来复制时,只是创建了对这个对象的引用,而不是真正的创建了它。 *3 创建了一个包含三个引用的列表,这三个引用都指向同一个长度为2的列表。其中一个行的改变会显示在所有行中,这当然不是你想要的。解决方法当然有,我们这样来创建

A = [None]*3
for i in range(3):
A[i] = [None] * 2

这样创建了一个包含三个不同的长度为2的列表。

所以,还是一直强调的,越复杂的东西,越灵活,也越容易出错。

代码优化

C是一个很简单的语言,当我们考虑优化的时候,通常想得也很简单,比如系统级调用越少越好(缓冲区机制),消除循环的低效率和不必要的系统引用,等
等,其实主要都是基于系统和硬件细节考虑的。而Python就完全不一样了,当然上面说的这些优化形式,对于Python仍然是实用的,但由于
Python的语法形式千差万别,库和模块多种多样,所以对于语言本身而言,就有很多值得注意的优化要点,举几个例子吧。

比如我们有一个list L1,想要构建一个新的list L2,L2包括L1的头4个元素。按照最直接的想法,代码应该是

L2 = []
for i in range[3]:
L2.append(L1[i])

而更加优化和优美的版本是

L2 = L1[:3]

再比如,如果s1..s7是大字符串(10K+),那么join([s1,s2,s3,s4,s5,s6,s7])就会比
s1+s2+s3+s4+s5+s6+s7快得多,因为后者会计算很多次子表达式,而join()则在一次过程中完成所有的复制。还有,对于字符串操作,
对字符串对象使用replace()方法。仅当在没有固定字符串模式时才使用正则表达式。

所以说,以优化为评判标准,如果说C是短小精悍,Python就是博大精深。

include和import

在C语言中的include非常简单,因为形式单一,意义明确,当你需要用到外部函数等资源时,就用include。而Python中有一个相似的
机制,就是import。乍一看,这两个家伙挺像的,不都是我们要用外部资源(最常见的就是函数或者模块(Python))时就用这个来指明么?其实不

然,两者的处理机制本质区别在于,C中的include是用于告诉预处理器,这个include指定的文件的内容,你都给我当作在本地源文件中出现过。而

import呢,不是简单的将后面的内容*直接*插入到本地里面去,这玩意更加灵活。事实上,几乎所有类似的机制,Python都比C灵活。这里不是说C
不好,C很简练,我其实更喜欢C。

简单说说这个灵活性。import在python中有三种形式,import X, from X import *( or a,b,c……),
X = __import__(’x')。最常用的是第二种,因为比较方便,不像第一种那样老是用X.mole来调用模块。from X
import *只是import那些public的mole(一般都是不以__命名的模块),也可以指定a,b,c来import。

什么时候用哪一种形式呢?应该说,在大多数的模块文档里,都会明确告诉你应该用哪种形式。如果需要用到很多对象,那么from X import
*可能更合适一些,但是,就目前来看,大多数第三方Python库都不推荐使用from molename import *
这种格式。这样做会使引入者的namespace混乱。很多人甚至对于那些专门设计用于这种模式的模块(包括Tkinter,
threading和matplot)都不采用这种方式。而如果你仅仅需要某个对象类a,那么用from X import a比用import
X.a更好,因为以后你调用a的函数直接用a.function()既可以了,不用加X。

如果你连自己希望import的模块都不知道怎么办?请注意,此时Python的优势就体现出来了,我们可以用
__import__(mole)来调用mole,其中这个mole是字符串,这样,可以在运行时再决定,你到底要调用什么mole。举
个例子:

def classFromMole (mole, Name):
mod = __import__ (mole)
return getattr (mod, Name)

这里,定义了一个函数classFromMole,你可以在代码的任何时候调用它,

o = classFromMole (MoleOfTheClass, NameOfTheAttribute)()

只需要传入字符串形式的你希望import的模块MoleOfTheClass和其中属性的名字NameOfTheAttribute(当然可以是数据也可以是方法),就能调用了,这个名字字符串不用事先指定,而是根据当时运行的情况来判断。

顺带说一句,Python中import的顺序也有默认规定,这个和C中的include有点类似,因为我们一般都是先include系统文件,再
include自己的头文件(而且还有<>和“”的区别)。Python中呢,一般应该按照以下顺序import模块:

1. 标准库模块 — 如 sys, os, getopt 等

2. 第三方模块

3. 本地实现的模块。

全局变量

这里谈全局变量呢,倒不是说Python和c的全局变量概念不同,他们的概念是相同的。只是在使用机制上,是有一些差异的。举个例子:

– mole.py –
globalvar = 1

def func():
print globalvar
# This makes someglobal readonly,
# any attempt to write to someglobal
# would create a new local variable.

def func2():
global globalvar
globalvar = 2
# this allows you to manipulate the global
# variable

在 func这个函数中,globalvar是只读的。如果你使用了globalvar =
xxx这种赋值语句,Python会重新创造一个新的本地对象并将新值赋给它,原来的对象值不变。而在func2函数中,由于我们事先申明了
globalvar是global的,那么此时的更改就直接在全局变量上生效。

6. js 和 python怎么交互

python取得javascript里面的值
复制代码代码如下:
import PyV8
with PyV8.JSContext() as env1:
env1.eval("""
var_i = 1;
var_f = 1.0;
var_s = "test";
var_b = true;
""")
vars = env1.locals
var_i = vars.var_i
print var_i
javascript取得python里面的值

复制代码代码如下:
import PyV8
with PyV8.JSContext() as env1:
env1.securityToken = "foo"
env1.locals.prop = 3
print int(env1.eval("prop"))
python和javascript里面的函数交互
python调用javascript里面的函数python调用func就可以使用js里面的function函数了
复制代码代码如下:
import PyV8
with PyV8.JSContext() as ctxt:
func = ctxt.eval("""
(function ()
{
function a()
{
return "abc";
}
return a();
})
""")
print func()
这样也可以
复制代码代码如下:
import PyV8
with PyV8.JSContext() as ctxt:
func = ctxt.eval("""
function a()
{
return "abc";
}
function c()
{
return "abc";
}
""")
a = ctxt.locals.a
print a()

7. 如何让python调用C和C++代码

如何让python调用和C++代码

安装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),假如我们接下来要写的扩展mole名为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_InitMole("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 mole", 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。