N...
>>>
创建hello.c
在工程中添加一个新文件,命名为hello.c
。复制下面内容。
//
// C code runs Python code in this module in embedded mode.
// print hello string
//
// www.moguf.com 2016-05-28
//
#include <python.h>
int main()
{
Py_Initialize();
PyRun_SimpleString("print('run python ...')");
PyRun_SimpleString("import script");
PyRun_SimpleString("print(script.message)");
PyRun_SimpleString("x = script.message");
PyRun_SimpleString("print(script.transform(x))");
Py_Finalize();
}
运行程序
在程序最后下个断点,方便查看运行结果。直接运行程序可以看到下面结果。
run python ...
hello life...
HELLO PYTHON...
基本调用流程解析
使用C程序运行Python脚本代码,可以通过使用Python字符串,调用Python对象或模板之类的所有操作。
流程:
1、初始化Python解析器
2、执行Python代码,字符串,对象或模块。
3、关闭Python解析器。
上面代码嵌入过程很容易。但在实际使用中想要更好的整合,须要了解提供的API和不同语言之间的转换。
Python嵌入C的基础API
下面几个基础API,在C中能很容易的执行Python脚本中的代码。包括字典、数组和对象。当然想要更好的混合交互须要熟悉所有的API。
PyImport_ImportModel |
import module |
PyImport_ReloadModule |
reload(module) |
PyImport_GetModuleDict |
module.__dict__ |
PyDict_GetItemString |
dict[key] |
PyDict_SetItemString |
dict[key] = value |
PyDict_New |
dict = {} |
PyObject_GetAttrString |
getattr(obj, attr) |
PyObject_SetAttrString |
setattr(obj, attr, val) |
PyObject_CallObject |
funcobj(*argstuple) |
Pyeva l_CallObject |
funcobj(*argstuple) |
PyRun_String |
eva l(exprstr) , exec(stmtstr) |
PyRun_File |
exec(open(filename().read()) |
建议: 去官网下载一个手册,方便查看API。https://docs.python.org/3/download.html
2.2、使用C扩展Python
2.1的内容只是通过C程序调用Python脚本,要让Python脚本能调用C代码,就须要扩展。用C扩展Python功能那就简单很多。有很多实例可以参考。Python源代码就是宝库。
创建扩展工程 hello
在VS中创建一个空的动态库hello
工程(先不要改名)。在工程配置中增加搜索路径。
在VS生成时有些特殊。生成的后缀选择.pyd主要是为防止和系统.dll产生冲突。
在工程选项界面中设置工程输出名称为$(ProjectName)_d
,输出扩展名称为.pyd
。
并在Linker页面Input组中设置库依赖为python35_d.lib
不同的编译模式的设置:
Release 下使用的依赖库为pythonXY.lib
Debug 下使用依赖库为 pythonXY_d.lib
注意:
debug 模式生成应为 hello_d.pyd
release 模式生成应为 hello.pyd
创建hello.c扩展代码
在工程中新建hello.c文件,复制下面内容。
//
// A simple C extension module for python, called "hello"
//
// www.moguf.com 2016-05-28
//
#include <python.h>
#include <string.h>
//
// module functions
//
static PyObject * // returns object
message(PyObject *self, PyObject *args)
{
char *fromPython, result[1024];
if (!PyArg_Parse(args, "(s)", &fromPython)) // convert Python -> C
return NULL; // exception null = raise
else {
strcpy(result, "Hello , "); // build up C string
strcat(result, fromPython); // add passed Python string
return Py_BuildValue("s", result); // convert C -> Python
}
}
//
// registration methods table
static PyMethodDef hello_methods[] = {
{ "message", message, METH_VARARGS, "func doc" }, // format: name, &func, fmt, doc
{ NULL, NULL, 0, NULL } // end
};
// module definition structure
static struct PyModuleDef hellomodule = {
PyModuleDef_HEAD_INIT,
"hello", // module name
"mod doc", // module documentation,
-1,
hello_methods // methods table
};
//
// module initializer
PyMODINIT_FUNC
PyInit_hello()
{
return PyModule_Create(&hellomodule);
}
上面的代码主要分为四块。
第一块: 模块功能实现函数
第二块: 注册功能函数
第三块: 定义模块申明
第四块: 初始化模块。动态加载就不需要这块内容,集成时会使用动态加载。
通过上述定义为Python脚本调用提供访问入口,这就是通常所说的胶水代码。具体定义直接看代