作成日: 2023-08-04 (金)
from setuptools import setup, Extension
setup(
name="pointlib",
ext_modules=[
Extension("pointlibmodule", ["pointlibmodule.c"])
]
)
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>
// clang-format off
typedef struct {
PyObject_HEAD
double x;
double y;
} PointObject;
// clang-format on
static int Point_init(PointObject *self, PyObject *args) {
double x, y;
if (!PyArg_ParseTuple(args, "dd", &x, &y)) {
return -1;
}
self->x = x;
self->y = y;
return 0;
}
static PyObject *Point_to_s(PointObject *self, PyObject *Py_UNUSED(ignored)) {
char buf[1024];
snprintf(buf, 1024, "(%lf,%lf)", self->x, self->y);
return PyUnicode_FromFormat("%s", buf);
}
static PyMemberDef Point_members[] = {
{"x", T_DOUBLE, offsetof(PointObject, x), 0, "x coord"},
{"y", T_DOUBLE, offsetof(PointObject, y), 0, "y coord"},
{NULL}};
static PyMethodDef Point_methods[] = {
{"to_s", (PyCFunction)Point_to_s, METH_NOARGS, "Return formated string."},
{NULL, NULL, 0, NULL}};
static PyTypeObject PointType = {
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "pointlib.Point",
.tp_doc = PyDoc_STR("Point object"),
.tp_basicsize = sizeof(PointObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = PyType_GenericNew,
.tp_init = (initproc)Point_init,
.tp_members = Point_members,
.tp_methods = Point_methods,
};
static PyObject *pointlib_distance(PyObject *self, PyObject *args) {
PyObject *pt1, *pt2;
if (!PyArg_ParseTuple(args, "OO", &pt1, &pt2)) {
return NULL;
}
PyObject *x1_obj = PyObject_GetAttrString(pt1, "x");
PyObject *y1_obj = PyObject_GetAttrString(pt1, "y");
PyObject *x2_obj = PyObject_GetAttrString(pt2, "x");
PyObject *y2_obj = PyObject_GetAttrString(pt2, "y");
if (x1_obj == NULL || y1_obj == NULL || x2_obj == NULL || y2_obj == NULL) {
Py_XDECREF(x1_obj);
Py_XDECREF(y1_obj);
Py_XDECREF(x2_obj);
Py_XDECREF(y2_obj);
return NULL;
}
double x1 = PyFloat_AsDouble(x1_obj);
double y1 = PyFloat_AsDouble(y1_obj);
double x2 = PyFloat_AsDouble(x2_obj);
double y2 = PyFloat_AsDouble(y2_obj);
double dx = x2 - x1;
double dy = y2 - y1;
double dist = sqrt(dx * dx + dy * dy);
Py_DECREF(x1_obj);
Py_DECREF(y1_obj);
Py_DECREF(x2_obj);
Py_DECREF(y2_obj);
return PyFloat_FromDouble(dist);
}
static PyMethodDef pointlib_methods[] = {
{"distance", pointlib_distance, METH_VARARGS,
PyDoc_STR("Distance between two points.")},
{NULL, NULL, 0, NULL}};
static PyModuleDef pointlib_module = {
PyModuleDef_HEAD_INIT,
.m_name = "pointlib",
.m_doc = PyDoc_STR("Example module creating custom type."),
.m_size = -1,
.m_methods = pointlib_methods,
};
PyMODINIT_FUNC PyInit_pointlib(void) {
if (PyType_Ready(&PointType) < 0) {
return NULL;
}
PyObject *module = PyModule_Create(&pointlib_module);
if (module == NULL) {
return NULL;
}
Py_INCREF(&PointType);
if (PyModule_AddObject(module, "Point", (PyObject *)&PointType) < 0) {
Py_DECREF(&PointType);
Py_DECREF(module);
return NULL;
}
return module;
}