ユーザ用ツール

サイト用ツール


youtube:python-mixing-003x2

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
youtube:python-mixing-003x2 [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1youtube:python-mixing-003x2 [2024/02/28 18:26] (現在) – ↷ toybox:python-mixing-003x2 から youtube:python-mixing-003x2 へページを移動しました。 freemikan
行 1: 行 1:
 +====== CでPythonのクラスを作る ======
 +
 +作成日: 2023-08-04 (金)
 +
 +[[https://youtu.be/kYp_yQfunhU|第3回 Python/C APIに触れてみる (2)]]
 +
 +===== ソースコード =====
 +
 +==== setup.py ====
 +
 +<file python>
 +from setuptools import setup, Extension
 +
 +setup(
 +    name="pointlib",
 +    ext_modules=[
 +        Extension("pointlibmodule", ["pointlibmodule.c"])
 +    ]
 +)
 +</file>
 +
 +==== pointlibmodule.c ====
 +
 +<file 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;
 +}
 +</file>
  

特に明示されていない限り、本Wikiの内容は次のライセンスに従います: CC0 1.0 Universal
CC0 1.0 Universal Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki