资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

python与c调用函数,c语言调用python

怎样让Python脚本与C++程序互相调用

二、Python调用C/C++

为甘泉等地区用户提供了全套网页设计制作服务,及甘泉网站建设行业解决方案。主营业务为做网站、成都网站设计、甘泉网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

1、Python调用C动态链接库

Python调用C库比较简单,不经过任何封装打包成so,再使用python的ctypes调用即可。

(1)C语言文件:pycall.c

[html] view plain copy

/***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 copy

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 copy

#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:"aendl;

}

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 copy

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 copy

#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="numendl;

cout"---end---"endl;

}

(2)编译成二进制可执行文件:g++ -o testmain main.cpp。

(3)Python调用程序:main.py

[html] view plain copy

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 copy

#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* Module_func()的包装函数;c、为每个模块增加一个型如PyMethodDef ModuleMethods[]的数组;d、增加模块初始化函数void initModule()。

python 字典调用C++函数

使用Python的ctypes,我们可以直接调用由C直接编译出来的函数。其实就是调用动态链接库中的函数。为什么我们需要这样做呢,因为有些时候,我们可能需要一个性能上比较讲究的算法,有些时候,我们可以在Python中使用已经有了的现成的被封闭在动态链接库中的函数。下面是如何调用的示例。

首先,我们用一个乘法来表示一个算法功能。下面是C的程序:

int multiply(int num1, int num2){   

return num1 * num2;

}    

如果在Windows下,你可能需要写成下面这个样子:

#include windows.h 

BOOL APIENTRYDll

Main(HANDLE hModule, DWORD dwReason, LPVOID lpReserved){    

return TRUE;

__declspec(dllexport) 

intmultiply(int num1, int num2){ 

return num1 * num2;

}    

然后,自然是把这个C文件编成动态链接库:

Linux下的编译:

gcc -c -fPIC libtest.c

gcc -shared libtest.o -o libtest.so    

Windows下的编译:

cl -LD libtest.c -libtest.dll    

于是在我们的Python中可以这样使用:

(其中的libtest.so在Windows下改成libtest.dll即可)

from ctypes import *

import os

libtest = cdll.LoadLibrary(os.getcwd() + '/libtest.so')

print libtest.multiply(2, 2)4    

注意:上面的Python脚本中需要把动态链接库放到当前目录中。

C语言程序如何调用python程序

下面是一个例子:

首先是python的一个简单函数

class Hello:

def __init__(self, x):

self.a = x

def print(self, x=None):

print(x)

def xprint():

print("hello world")

if __name__ == "__main__":

xprint()

h = Hello(5)

h.print()1

下面是C语言

#include python3.4m/Python.h

#include stdio.h

#include stdlib.h

#include string.h

int main()

{

Py_Initialize();

// 将当前目录加入sys.path

PyRun_SimpleString("import sys");

PyRun_SimpleString("sys.path.append('./')");

// 导入hello.py模块

PyObject *pmodule = PyImport_ImportModule("hello");

// 获得函数xprint对象,并调用,输出“hello world\n”

PyObject *pfunc = PyObject_GetAttrString(pmodule, "xprint");

PyObject_CallFunction(pfunc, NULL);

// 获得类Hello并生成实例pinstance,并调用print成员函数,输出“5 6\n”

PyObject *pclass = PyObject_GetAttrString(pmodule, "Hello");

PyObject *arg = Py_BuildValue("(i)", 5);

PyObject *pinstance = PyObject_Call(pclass, arg, NULL);

PyObject_CallMethod(pinstance, "print", "i", 6);

Py_Finalize();

return 0;

}

编译命令如下:

gcc pyapi.c -lpython3.4m -o pyapi

python使用ctypes调用C编译dll函数方法

在函数声明加入前缀,如

__declspec(dllexport) int Fun(int a, int b)

否则在加载该dll时会提示找不到该符号

在windows下可以通过vs自带的dumpbin工具查看可被调用符号

dumpbin /exports test.dll

C函数在调用过程中关于参数传递和压栈由多种规定,作为dll提供给其他程序调用时,必须明确并统一为同一种调用规定,否则会导致栈破坏,编译器负责具体实现调用规定,主要有以下几种调用规定

python下调用C库有多种方式,ctypes是其中一种比较方便的,调用时首先需要加载dll文件,根据C dll的调用规定不同需要使用不同接口,使用ctypes需要 import ctypes 库

对于简单的C函数,例如 int add(int a, int b) , 此时就可以直接调用了,如

对于较复杂的C函数的参数情况,ctypes调用时对入参和出餐做一定处理,这里分情况讨论

以上包含了几种主要的参数传递情况,ctypes也提供了一个较为完整的python类型和C类型的对照,如下:


名称栏目:python与c调用函数,c语言调用python
文章起源:http://cdkjz.cn/article/hsiiod.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220