Python 與 C 擴充 -簡單函式

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

回到目錄
https://husking-studio.com/extending-python-with-c

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *