Python 與 C 擴充 -C++類別
環境
windows 11 64bit
Visual Studio 2022
python 3.12.2 64bit
mytestmodule.cpp
#include <C:\Python312\include\Python.h>
#include <C:\Python312\include\structmember.h>
typedef struct {
PyObject_HEAD
int number;
char name[128];
} MyTest;
static PyObject *MyTest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
MyTest *self;
self = (MyTest *)type->tp_alloc(type, 0);
if (self != NULL)
{
//TODO : constructor
self->number = 0;
strcpy(self->name, "def");
}
return (PyObject *)self;
}
static void MyTest_dealloc(MyTest* self)
{
//TODO : destructor
Py_TYPE(self)->tp_free((PyObject*)self);
}
static int MyTest_init(MyTest *self, PyObject *args, PyObject *kwds)
{
//TODO : member variable
PyObject *first=NULL, *last=NULL, *tmp;
static char *kwlist[] = {"number", "name", NULL};
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|is", kwlist,
&self->number, self->name))
return -1;
return 0;
}
static PyMemberDef MyTest_members[] = {
//TODO : member variable
{"number", T_INT, offsetof(MyTest, number), 0, "MyTest number"},
{"name", T_CHAR, offsetof(MyTest, name), 0, "MyTest name"},
{NULL} /* Sentinel */
};
//TODO : member function
static PyObject *MyTest_TestPrint(MyTest* self, PyObject *args)
{
char sz[1024];
sprintf(sz, "MyTest_TestPrint");
return Py_BuildValue("s", sz);
}
static PyObject *MyTest_Add(MyTest* self, PyObject *args)
{
int nA;
if (!PyArg_ParseTuple(args, "i", &nA))
return NULL;
self->number = self->number + nA;
return Py_BuildValue("i", self->number);
}
static PyObject *MyTest_SetName(MyTest* self, PyObject *args)
{
const char *command;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
strcpy(self->name, command);
return Py_BuildValue("");
}
static PyObject *MyTest_GetName(MyTest* self, PyObject *args)
{
return Py_BuildValue("s", self->name);
}
//TODO : member function
static PyMethodDef MyTest_methods[] = {
{"TestPrint", (PyCFunction)MyTest_TestPrint, METH_NOARGS, "TestPrint"},
{"Add", (PyCFunction)MyTest_Add, METH_VARARGS, "Add"},
{"SetName", (PyCFunction)MyTest_SetName, METH_VARARGS, "SetName"},
{"GetName", (PyCFunction)MyTest_GetName, METH_NOARGS, "GetName"},
{NULL} /* Sentinel */
};
static PyTypeObject MyTestType = {
PyVarObject_HEAD_INIT(NULL, 0) /*ob_size*/
"MyTest.MyTest", /*tp_name*/
sizeof(MyTest), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)MyTest_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"MyTest objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
MyTest_methods, /* tp_methods */
MyTest_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)MyTest_init, /* tp_init */
0, /* tp_alloc */
MyTest_new, /* tp_new */
};
static PyModuleDef MyTestmodule = {
PyModuleDef_HEAD_INIT,
"MyTest",
"Example module that creates an extension type.",
-1,
NULL, NULL, NULL, NULL, NULL
};
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC PyInit_mytestmodule(void)
{
PyObject* m;
if (PyType_Ready(&MyTestType) < 0)
return NULL;
m = PyModule_Create(&MyTestmodule);
if (m == NULL)
return NULL;
Py_INCREF(&MyTestType);
PyModule_AddObject(m, "MyTest", (PyObject *)&MyTestType);
return m;
}
compile.bat(debug版)
cl /LDd /MDd mytestmodule.cpp C:\Python312\libs\python3.lib C:\Python312\libs\python312_d.lib
copy mytestmodule.dll mytestmodule.pyd
openvc.bat
@echo off
%comspec% /k ""C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat"" x64
執行 openvc.bat,輸入 compile
編譯成功,會產生 mytestmodule.pyd
test.py
import mytestmodule
p = mytestmodule.MyTest()
print(p.number)
p.number = 3
print(p.number)
print(p.Add(10))
print(p.number)
print(p.GetName())
p.SetName("abc")
print(p.GetName())
執行 test.py 結果
回到目錄
https://husking-studio.com/extending-python-with-c
未解決問題 print(p.name) 會只印出第一個字元…. |