参考文章
官方文档 https://docs.python.org/3/extending/extending.html#calling-python-functions-from-c
微软文档 https://docs.microsoft.com/en-us/visualstudio/python/cpp-and-python
微软文档的例子比较简单一些,我就就拷贝它的例子。如果python也用vs集成开发环境,你还可以debug 你的c扩展,里面也有介绍。
在vs里新建一个空项目,然后设置 target extension 和 configuration type, target extension 可以为dll或者pyd,但如果设置为dll的话,到时候记得把编译后的dll后缀
手动改成pyd,因为python import的时候,默认去找py pyd等后缀的,不找dll为后缀的,如果只是dll的会出现 ModuleNotFoundError: No module named xx
因为需要使用到python.h, 你需要把python安装目录下的 包含python.h 的include包含进来,还需要设置python lib目录以及 lib
我用的是anaconda3。
#include "python.h"
PyObject* tanh_impl(PyObject *, PyObject* o) {
double x = PyFloat_AsDouble(o);
double tanh_x = x/10;
return PyFloat_FromDouble(tanh_x);
}
static PyMethodDef hello_methods[] = {
// The first property is the name exposed to python, the second is the C++ function name
{ "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr },
// Terminate the array with an object containing nulls.
{ nullptr, nullptr, 0, nullptr }
};
static PyModuleDef hello_module = {
PyModuleDef_HEAD_INIT,
"hello", // Module name
"Provides some functions, but faster", // Module description
0,
hello_methods // Structure that defines the methods
};
PyMODINIT_FUNC PyInit_hello() {
return PyModule_Create(&hello_module);
}
extern "C" __declspec(dllexport) int testExport(){
printf(__FUNCTION__);
return 0;
}
编译出来后 如果用 import 的方式使用这个 hello.pyd
>>> import hello
>>> hello.__dict__
{'__name__': 'hello', '__doc__': 'Provides some functions, but faster', '__packa
ge__': '', '__loader__': <_frozen_importlib_external.ExtensionFileLoader object
at 0x00000000027CC320>, '__spec__': ModuleSpec(name='hello', loader=<_frozen_imp
ortlib_external.ExtensionFileLoader object at 0x00000000027CC320>, origin='D:\\c
ode\\test\\x64\\Release\\hello.pyd'), 'fast_tanh':
, '__file__': 'D:\\code\\test\\x64\\Release\\hello.pyd'}
>>> dir(hello)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fast_tanh']
>>> hello.fast_tanh(20)
2.0
可以看到我们想导出的 fast_tanh是在里面的,可以像使用python模块一样正常使用。
这个例子中我增加了一个 testExport()函数,这个testExport只能通过ctypes导入dll的方式使用,
详见 ctypes的官方文档,ctypes提供了python直接调用dll中导出函数的功能。LoadLibrary 无所谓dll还是pyd,只要文件名正确即可。
import ctypes
hello = ctypes.cdll.LoadLibrary("hello.dll")
>>> hello.testExport()
testExport0
这是python和 C函数的交互。