189 8069 5689

python和c接口函数,python与C语言

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/C++ 与 Python 的通信

这个事情做过好多遍,摸索的过程基本这样的:

1. 通过stdout通信...土到爆,但上手极快,简单粗暴;

2. 调用原始的python.h 接口,编写可以被python import 的so,支持python调用c++接口,c++接口调用python同样的方式;

3. 使用boost-python 完成2中的功能,接口简单很多,本质上没有不同;

这里遇到的主要几个问题在于:

1. 数据的序列化反序列化,因为有时c++和python之间通信的不是基本类型,可能是用户自定义类型;

2. 多线程的问题,c++多线程调python接口时,需要注意GIL的使用,貌似因为python解释器不是线程安全的;

3.

对象传递,大多数情况下,如果只是静态接口调用,都比较简单,考虑一种情况:c++中的对象的一个函数调用python一个接口,这个python接口中

又需要反过来调用这个对象中的另一个接口,这里就需要考虑怎么把对象相互传递,我这里是把对象指针地址传递到python中,在python中调用一个

c++的静态接口,带上地址和其他需要的参数,在这个c++的静态接口中,把地址转换成指针在调用..

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

要搞明白如何让python调用C/C++代码(也就是写python的extension),你需要征服手册中的Extending embedding厚厚的一章。在昨天花了一个小时看地头晕脑胀,仍然不知道如何写python的extension后,查阅了一些其他书籍,最终在Python Programming On Win32书中找到了教程。

1. 首先要明白的是,所谓的python扩展(也就是你提供给python的c/c++代码,不一定是c/c++代码,可以是其他语言写的代码)是一个dll,并且这个dll放在本机python安装目录下的DLLs目录下(譬如我机器上的路径是:F:/Program Files/Python25/DLLs),假如我们接下来要写的扩展module名为mb,python调用的代码为:import mbmb.showMsg("Python's really amazing, I kindda love it!")

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里去调用

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;//调用MBint 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 mbmb.showMsg("Python's really amazing, I kindda love it!")

python调用c函数

Python是解释性语言, 底层就是用c实现的, 所以用python调用C是很容易的, 下面就总结一下各种调用的方法, 给出例子, 所有例子都在ubuntu9.10, python2.6下试过

1. Python 调用 C (base)

想在python中调用c函数, 如这儿的fact

#include Python.h

int fact(int n)

{

if (n = 1)

return 1;

else

return n * fact(n - 1);

}

PyObject* wrap_fact(PyObject* self, PyObject* args)

{

int n, result;

if (! PyArg_ParseTuple(args, "i:fact", n))

return NULL;

result = fact(n);

return Py_BuildValue("i", result);

}

static PyMethodDef exampleMethods[] =

{

{"fact", wrap_fact, METH_VARARGS, "Caculate N!"},

{NULL, NULL}

};

void initexample()

{

PyObject* m;

m = Py_InitModule("example", exampleMethods);

}

把这段代码存为wrapper.c, 编成so库,

gcc -fPIC wrapper.c -o example.so -shared -I/usr/include/python2.6 -I/usr/lib/python2.6/config

然后在有此so库的目录, 进入python, 可以如下使用

import example

example.fact(4)

2. Python 调用 C++ (base)

在python中调用C++类成员函数, 如下调用TestFact类中的fact函数,

#include Python.h

class TestFact{

public:

TestFact(){};

~TestFact(){};

int fact(int n);

};

int TestFact::fact(int n)

{

if (n = 1)

return 1;

else

return n * (n - 1);

}

int fact(int n)

{

TestFact t;

return t.fact(n);

}

PyObject* wrap_fact(PyObject* self, PyObject* args)

{

int n, result;

if (! PyArg_ParseTuple(args, "i:fact", n))

return NULL;

result = fact(n);

return Py_BuildValue("i", result);

}

static PyMethodDef exampleMethods[] =

{

{"fact", wrap_fact, METH_VARARGS, "Caculate N!"},

{NULL, NULL}

};

extern "C" //不加会导致找不到initexample

void initexample()

{

PyObject* m;

m = Py_InitModule("example", exampleMethods);

}

把这段代码存为wrapper.cpp, 编成so库,

g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.6 -I/usr/lib/python2.6/config

然后在有此so库的目录, 进入python, 可以如下使用

import example

example.fact(4)

3. Python 调用 C++ (Boost.Python)

Boost库是非常强大的库, 其中的python库可以用来封装c++被python调用, 功能比较强大, 不但可以封装函数还能封装类, 类成员.

首先在ubuntu下安装boost.python, apt-get install libboost-python-dev

#include boost/python.hpp

char const* greet()

{

return "hello, world";

}

BOOST_PYTHON_MODULE(hello)

{

using namespace boost::python;

def("greet", greet);

}

把代码存为hello.cpp, 编译成so库

g++ hello.cpp -o hello.so -shared -I/usr/include/python2.5 -I/usr/lib/python2.5/config -lboost_python-gcc42-mt-1_34_1

此处python路径设为你的python路径, 并且必须加-lboost_python-gcc42-mt-1_34_1, 这个库名不一定是这个, 去/user/lib查

然后在有此so库的目录, 进入python, 可以如下使用

import hello

hello.greet()

'hello, world'

4. python 调用 c++ (ctypes)

ctypes is an advanced ffi (Foreign Function Interface) package for Python 2.3 and higher. In Python 2.5 it is already included.

ctypes allows to call functions in dlls/shared libraries and has extensive facilities to create, access and manipulate simple and complicated C data types in Python - in other words: wrap libraries in pure Python. It is even possible to implement C callback functions in pure Python.

#include Python.h

class TestFact{

public:

TestFact(){};

~TestFact(){};

int fact(int n);

};

int TestFact::fact(int n)

{

if (n = 1)

return 1;

else

return n * (n - 1);

}

extern "C"

int fact(int n)

{

TestFact t;

return t.fact(n);

}

将代码存为wrapper.cpp不用写python接口封装, 直接编译成so库,

g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.6 -I/usr/lib/python2.6/config

进入python, 可以如下使用

import ctypes

pdll = ctypes.CDLL('/home/ubuntu/tmp/example.so')

pdll.fact(4)

12

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语言接口

ctypes:  可直接调用c语言动态链接库。

使用步骤:

1 编译好自己的动态连接库

2 利用ctypes载入动态连接库

3 用ctype调用C函数接口时,需要将python变量类型做转换后才能作为函数参数,转换原则见下图:

4 Python若想获取ctypes调用的C函数返回值,需要先指定返回值类型。我们将在接下来的完整Sample中看到如何使用。

#Step 1:  test.c#include stdio.h

int add(int a, int b)

{

return a + b;

}#Step 2: 编译动态链接库 ( 如何编译动态链接库在本文不详解,网上资料一大堆。)gcc -fPIC -shared test.c -o libtest.so  

#Step 3:  test.py

from ctypes import *mylib = CDLL("libtest.so")   或者   cdll.LoadLibrary("libtest.so")   add = mylib.add

add.argtypes = [c_int, c_int] # 参数类型,两个int(c_int是ctypes类型,见上表)

add.restype = c_int # 返回值类型,int (c_int 是ctypes类型,见上表)

sum = add(3, 6)


本文名称:python和c接口函数,python与C语言
新闻来源:http://cdxtjz.cn/article/hdheie.html

其他资讯