Python 與 C 擴充 -簡單函式
環境
windows 11 64bit
Visual Studio 2022
python 3.12.2 64bit
安裝 python 之後,要確認環境變數,我是把 python 安裝在 C:\Python312
spam.cpp
#include <C:\Python312\include\Python.h>
static PyObject *SpamError;
static PyObject *spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
if (sts < 0)
{
PyErr_SetString(SpamError, "System command failed");
return NULL;
}
return PyLong_FromLong(sts);
}
static PyObject *spam_add(PyObject *self, PyObject *args)
{
int a;
int b;
if (!PyArg_ParseTuple(args, "ii", &a, &b))
return NULL;
int sum = a + b;
return Py_BuildValue("i", sum);
}
static PyMethodDef SpamMethods[] = {
{"system", spam_system, METH_VARARGS,
"Execute a shell command."},
{"add", spam_add, METH_VARARGS,
"Add two numbers."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef spammodule = {
PyModuleDef_HEAD_INIT,
"spam", /* name of module */
0, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
SpamMethods
};
PyMODINIT_FUNC PyInit_spam(void)
{
PyObject *m;
m = PyModule_Create(&spammodule);
if (m == NULL)
return NULL;
SpamError = PyErr_NewException("spam.error", NULL, NULL);
Py_INCREF(SpamError);
PyModule_AddObject(m, "error", SpamError);
return m;
}
compile.bat(debug版)
cl /LDd /MDd spam.cpp C:\Python312\libs\python3.lib C:\Python312\libs\python312_d.lib
copy spam.dll spam.pyd
openvc.bat
@echo off
%comspec% /k ""C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat"" x64
執行 openvc.bat,輸入 compile
會出現錯誤
fatal error LNK1181: cannot open input file ‘C:\Python311\libs\python312_d.lib’ 或 fatal error LNK1181: cannot open input file ‘python312_d.lib’ 或 fatal error LNK1181: 無法開啟輸入檔 ‘C:\Python311\libs\python312_d.lib’ |
找到 C:\Python312\libs 資料夾,從 python312.lib 複製出一個 python312_d.lib
再次編譯
會出現錯誤
spam.obj : error LNK2019: 在函式 __imp__Py_INCREF_IncRefTotalPy_INCREF 中參考了無法解析的外部符號
spam.dll : fatal error LNK1120: 1 個無法解析的外部符號
在 C:\Python312\include 資料夾找到 pyconfig.h
把
#ifdef _DEBUG # define Py_DEBUG #endif |
改成
#ifdef _DEBUG //# define Py_DEBUG #endif |
再次編譯
編譯成功,會產生 spam.pyd,最重要的就是這個 spam.pyd
test.py
import spam
spam.system("dir")
print("a+b = ", spam.add(10, 20))
執行 test.py