#include
-I/usr/include/python2.7/
Makefile的编写
这里提供了一个Makefile的编写供参考:
CC = gcc
CFLAGS = -g -Wall
TARGET = test
INC = -I/usr/include/python2.7/
LIB = -L/usr/lib -lpython2.7
all: clean $(TARGET)
test: test.o
$(CC) -o $(TARGET) test.o $(LIB)
test.o: test.c
$(CC) -c test.c $(CFLAGS)
clean:
rm -rf *.o $(TARGET)
最简单的调用
此种对Python的调用称为low level,应用于C程序中进行一些简单Python语句的调用。
#include "/usr/include/python2.7/Python.h"
void
deal_error(const char *str)
{
fprintf(stderr, "%s\n", str);
exit(EXIT_FAILURE);
}
int
main()
{
//初始化Python解释器
//任何C与Python的交互都需要在最开始调用此函数
Py_Initialize();
if(!Py_IsInitialized()) {
deal_error("Cannot init Python interpreter!");
}
//执行简单的Python的命令
PyRun_SimpleString("print 'Hello World'");
return 0;
}
进一步的调用
这种调用称为high level,更多情况下,我们更需要这种方法来对自己编写、系统的模块和函数、第三方库进行调用。
test.c
#include "/usr/include/python2.7/Python.h"
void
deal_error(const char *str)
{
fprintf(stderr, "%s\n", str);
exit(EXIT_FAILURE);
}
int
main()
{
PyObject *p_name = NULL, *p_module = NULL, *p_dict = NULL,
*p_func = NULL;
//初始化Python解释器
//任何C与Python的交互都需要在最开始调用此函数
Py_Initialize();
if(!Py_IsInitialized()) {
deal_error("Cannot init Python interpreter!");
}
//执行简单的Python的命令
//这里主要是在Python搜索文件的路径里加上当前路径
//否则不能找到对应的文件,也就不能加载对应的模块
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
//导入Python模块
//对应的文件名,去掉py的后缀
p_name = PyString_FromString("1");
p_module = PyImport_Import(p_name);
if(!p_module) {
deal_error("Cannot load the module!");
}
//此函数获取模块中的函数列表
p_dict = PyModule_GetDict(p_module);
if(!p_dict) {
deal_error("Cannot get the dict");
}
//查找函数的位置
p_func = PyDict_GetItemString(p_dict, "hello");
if(!p_func || !PyCallable_Check(p_func)) {
deal_error("Cannot find the function");
}
//调用函数
PyObject_CallObject(p_func, NULL);
//指针的释放
Py_DECREF(p_name);
Py_DECREF(p_module);
Py_DECREF(p_dict);
Py_DECREF(p_func);
//关闭Python
Py_Finalize();
return 0;
}
PS: 名字不要起test.py,因Python中自带test模块,导入后自然找不到你自己创建的函数
#!/usr/bin/env python
#-*- coding: utf-8 -*-
def hello():
print 'hello'
含有参数的调用
含有参数的调用比较复杂,除了涉及参数压栈等,还有C数据类型和Python数据类型转换的问题。这里只是简单的提了些用法。
一个例子(后有详细说明):
test.c
#include "/usr/include/python2.7/Python.h"
void
deal_error(const char *str)
{
fprintf(stderr, "%s\n", str);
exit(EXIT_FAILURE);
}
int
main()
{
PyObject *p_name = NULL, *p_module = NULL, *p_dict = NULL,
*p_func = NULL, *p_args = NULL;
//初始化Python解释器
//任何C与Python的交互都需要在最开始调用此函数
Py_Initialize();
if(!Py_IsInitialized()) {
deal_error("Cannot init Python interpreter!");
}
//执行简单的Python的命令
//这里主要是在Python搜索文件的路径里加上当前路径
//否则不能找到对应的文件,也就不能加载对应的模块
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
//导入Python模块
//对应的文件名,去掉py的后缀
p_name = PyString_FromString("1");
p_module = PyImport_Import(p_name);
if(!p_module) {
deal_error("Cannot load the module!");
}
//此函数获取模块中的函数列表
p_dict = PyModule_GetDict(p_module);
if(!p_dict) {
deal_error("Cannot get the dict");
}
//查找函数的位置
p_func = PyDict_GetItemString(p_dict, "add");
if(!p_func || !PyCallable_Check(p_func)) {
deal_error("Cannot find the function");
}
p_args = PyTuple_New(2);
PyTuple_SetItem(p_args, 0, Py_BuildValue("i", 3));
PyTuple_SetItem(p_args, 1, Py_BuildValue("i", 4));
//调用函数
PyObject_CallObject(p_func, p_args);
//指针的释放
Py_DECREF(p_name);
Py_DECREF(p_module);
Py_DECREF(p_dict);
Py_DECREF(p_func);
//关闭Python
Py_Finalize();
return 0;
}
#!/usr/bin/env python
#-*- coding: utf-8 -*-
def add(a, b):
print a+b
PyObject* PyTuple_New( Py_ssize_t len);
之后就是设置每个参数,利用PyTuple_SetItem
int PyTuple_SetItem( PyObject *p, Py_ssize_t pos, PyObject *o);
p是要设置的参数元祖,也就是刚才新建的那个,pos是设置A元素的位置, o是所添加元素的值,这里涉及到Py_BuildValue的用法
Py_BuildValue主要是提供格式化的参数类型,例如整数,浮点数,字符串等。具体用法见:http://docs.python.org/release/1.5.2p2/ext/buildValue.html
当Python中函数有返回值的时候, 将调用函数的方式改成如下就可以:
int ret;
PyObject *p_retval = NULL;
p_retval = PyObject_CallObject(p_func, p_args);
PyArg_Parse(p_retval, "i", &ret);
以上只是简单介绍,Python和C的类型互相转换还比较麻烦,详细函数:
通过C类型生成Python类型:
http://docs.python.org/release/1.5.2p1/api/node24.html
Python转换为C类型:
http://docs.python.org/2/c-api/concrete.html
C调用Python的官方文档:
http://docs.python.org/2/c-api/index.html