GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — python-docs-ru/extending/first-extension-module.po at 3.15 · python/python-docs-ru Expand file tree/ Copy pathfirst-extension-module.poMore file actions 917 lines (771 loc) · 25.8 KB / Copy pathfirst-extension-module.poFile metadata and controls917 lines (771 loc) · 25.8 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 # SOME DESCRIPTIVE TITLE. # Copyright (C) 2001 Python Software Foundation # This file is distributed under the same license as the Python package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # # Translators: # Dmitry Luschan, 2026 # python-doc bot, 2026 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Python 3.15\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-10-31 18:01+0000\n" "PO-Revision-Date: 2026-05-08 18:36+0000\n" "Last-Translator: python-doc bot, 2026\n" "Language-Team: Russian (https://app.transifex.com/python-doc/teams/5390/" "ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " "(n%100>=11 && n%100<=14)? 2 : 3);\n" msgid "Your first C API extension module" msgstr "" msgid "" "This tutorial will take you through creating a simple Python extension " "module written in C or C++." msgstr "" msgid "" "We will use the low-level Python C API directly. For easier ways to create " "extension modules, see the :ref:`recommended third party tools <c-api-" "tools>`." msgstr "" msgid "" "The tutorial assumes basic knowledge about Python: you should be able to " "define functions in Python code before starting to write them in C. " "See :ref:`tutorial-index` for an introduction to Python itself." msgstr "" msgid "" "The tutorial should be approachable for anyone who can write a basic C " "library. While we will mention several concepts that a C beginner would not " "be expected to know, like ``static`` functions or linkage declarations, " "understanding these is not necessary for success." msgstr "" msgid "" "We will focus on giving you a \"feel\" of what Python's C API is like. It " "will not teach you important concepts, like error handling and reference " "counting, which are covered in later chapters." msgstr "" msgid "" "We will assume that you use a Unix-like system (including macOS and Linux), " "or Windows. On other systems, you might need to adjust some details -- for " "example, a system command name." msgstr "" msgid "" "You need to have a suitable C compiler and Python development headers " "installed. On Linux, headers are often in a package like ``python3-dev`` or " "``python3-devel``." msgstr "" msgid "" "You need to be able to install Python packages. This tutorial uses `pip " "<https://pip.pypa.io/>`__ (``pip install``), but you can substitute any tool " "that can build and install ``pyproject.toml``-based projects, like `uv " "<https://docs.astral.sh/uv/>`_ (``uv pip install``). Preferably, have " "a :ref:`virtual environment <venv-def>` activated." msgstr "" msgid "" "This tutorial uses APIs that were added in CPython 3.15. To create an " "extension that's compatible with earlier versions of CPython, please follow " "an earlier version of this documentation." msgstr "" msgid "" "This tutorial uses C syntax added in C11 and C++20. If your extension needs " "to be compatible with earlier standards, please follow tutorials in " "documentation for Python 3.14 or below." msgstr "" msgid "What we'll do" msgstr "" msgid "" "Let's create an extension module called ``spam`` [#why-spam]_, which will " "include a Python interface to the C standard library " "function :c:func:`system`. This function is defined in ``stdlib.h``. It " "takes a C string as argument, runs the argument as a system command, and " "returns a result value as an integer. A manual page for :c:func:`system` " "might summarize it this way::" msgstr "" msgid "" "#include <stdlib.h>\n" "int system(const char *command);" msgstr "" msgid "" "Note that like many functions in the C standard library, this function is " "already exposed in Python. In production, use :py:func:`os.system` " "or :py:func:`subprocess.run` rather than the module you'll write here." msgstr "" msgid "We want this function to be callable from Python as follows:" msgstr "" msgid "" ">>> import spam\n" ">>> status = spam.system(\"whoami\")\n" "User Name\n" ">>> status\n" "0" msgstr "" msgid "" "The system command ``whoami`` prints out your username. It's useful in " "tutorials like this one because it has the same name on both Unix and " "Windows." msgstr "" msgid "Start with the headers" msgstr "" msgid "" "Begin by creating a directory for this tutorial, and switching to it on the " "command line. Then, create a file named :file:`spammodule.c` in your " "directory. [#why-spammodule]_" msgstr "" msgid "" "In this file, we'll include two headers: :file:`Python.h` to pull in all " "declarations of the Python C API, and :file:`stdlib.h` for " "the :c:func:`system` function. [#stdlib-h]_" msgstr "" msgid "Add the following lines to :file:`spammodule.c`:" msgstr "" msgid "" "#include <Python.h>\n" "#include <stdlib.h> // for system()\n" msgstr "" msgid "" "Be sure to put :file:`stdlib.h`, and any other standard library includes, " "*after* :file:`Python.h`. On some systems, Python may define some pre-" "processor definitions that affect the standard headers." msgstr "" msgid "Running your build tool" msgstr "" msgid "" "With only the includes in place, your extension won't do anything. Still, " "it's a good time to compile it and try to import it. This will ensure that " "your build tool works, so that you can make and test incremental changes as " "you follow the rest of the text." msgstr "" msgid "" "CPython itself does not come with a tool to build extension modules; it is " "recommended to use a third-party project for this. In this tutorial, we'll " "use `meson-python`_. (If you want to use another one, see :ref:`first-" "extension-other-tools`.)" msgstr "" msgid "``meson-python`` requires defining a \"project\" using two extra files." msgstr "" msgid "First, add ``pyproject.toml`` with these contents:" msgstr "" msgid "" "[build-system]\n" "build-backend = 'mesonpy'\n" "requires = ['meson-python']\n" "\n" "[project]\n" "# Placeholder project information\n" "# (change this before distributing the module)\n" "name = 'sampleproject'\n" "version = '0'" msgstr "" msgid "Then, create ``meson.build`` containing the following:" msgstr "" msgid "" "project('sampleproject', 'c')\n" "\n" "py = import('python').find_installation(pure: false)\n" "\n" "py.extension_module(\n" " 'spam', # name of the importable Python module\n" " 'spammodule.c', # the C source file\n" " install: true,\n" ")" msgstr "" msgid "" "See the `meson-python documentation <meson-python_>`_ for details on " "configuration." msgstr "" msgid "" "Now, build install the *project in the current directory* (``.``) via " "``pip``:" msgstr "" msgid "python -m pip -v install ." msgstr "" msgid "" "The ``-v`` (``--verbose``) option causes ``pip`` to show the output from the " "compiler, which is often useful during development." msgstr "" msgid "" "If you don't have ``pip`` installed, run ``python -m ensurepip``, preferably " "in a :ref:`virtual environment <venv-def>`. (Or, if you prefer another tool " "that can build and install ``pyproject.toml``-based projects, use that.)" msgstr "" msgid "" "Note that you will need to run this command again every time you change your " "extension. Unlike Python, C has an explicit compilation step." msgstr "" msgid "" "When your extension is compiled and installed, start Python and try to " "import it. This should fail with the following exception:" msgstr "" msgid "" ">>> import spam\n" "Traceback (most recent call last):\n" " ...\n" "ImportError: dynamic module does not define module export function " "(PyModExport_spam or PyInit_spam)" msgstr "" msgid "Module export hook" msgstr "" msgid "" "The exception you got when you tried to import the module told you that " "Python is looking for a \"module export function\", also known as " "a :ref:`module export hook <extension-export-hook>`. Let's define one." msgstr "" msgid "First, add a prototype below the ``#include`` lines:" msgstr "" msgid "" "\n" "PyMODEXPORT_FUNC PyModExport_spam(void);\n" "\n" msgstr "" msgid "" "The prototype is not strictly necessary, but some modern compilers emit " "warnings without it. It's generally better to add the prototype than to " "disable the warning." msgstr "" msgid "" "The :c:macro:`PyMODEXPORT_FUNC` macro declares the function's return type, " "and adds any special linkage declarations needed to make the function " "visible and usable when CPython loads it." msgstr "" msgid "" "After the prototype, add the function itself. For now, make it return " "``NULL``:" msgstr "" msgid "" "PyMODEXPORT_FUNC\n" "PyModExport_spam(void)\n" "{\n" " return NULL;\n" "}" msgstr "" msgid "" "Compile and load the module again. You should get a different error this " "time." msgstr "" msgid "" ">>> import spam\n" "Traceback (most recent call last):\n" " ...\n" "SystemError: module export hook for module 'spam' failed without setting an " "exception" msgstr "" msgid "" "Simply returning ``NULL`` is *not* correct behavior for an export hook, and " "CPython complains about it. That's good -- it means that CPython found the " "function! Let's now make it do something useful." msgstr "" msgid "The slot table" msgstr "" msgid "" "Rather than ``NULL``, the export hook should return the information needed " "to create a module. Let's start with the basics: the name and docstring." msgstr "" msgid "" "The information should be defined in an array of :c:type:`PySlot` entries, " "which are essentially key-value pairs. Define this array just before your " "export hook:" msgstr "" msgid "" "PyABIInfo_VAR(abi_info);\n" "\n" "static PySlot spam_slots[] = {\n" " PySlot_STATIC_DATA(Py_mod_abi, &abi_info),\n" " PySlot_STATIC_DATA(Py_mod_name, \"spam\"),\n" " PySlot_STATIC_DATA(Py_mod_doc, \"A wonderful module with an example " "function\"),\n" " PySlot_END\n" "};" msgstr "" msgid "" "The :c:macro:`PySlot_STATIC_DATA` macro is used when the slot value (here: " "``&abi_info``, ``\"spam\"``, and the docstring) is a pointer to constant, " "statically allocated data." msgstr "" msgid "" "The ``PyABIInfo_VAR(abi_info);`` macro and the :c:data:`Py_mod_abi` slot are " "a bit of boilerplate that helps prevent extensions compiled for a different " "version of Python from crashing the interpreter." msgstr "" msgid "" "For both :c:data:`Py_mod_name` and :c:data:`Py_mod_doc`, the values are C " "strings -- that is, NUL-terminated, UTF-8 encoded byte arrays." msgstr "" msgid "" "Note ``PySlot_END`` sentinel entry at the end. This marks the end of the " "array. If you forget it, you'll trigger undefined behavior." msgstr "" msgid "" "The array is defined as ``static`` -- that is, not visible outside this " "``.c`` file. This will be a common theme. CPython only needs to access the " "export hook; all global variables and all other functions should generally " "be ``static``, so that they don't clash with other extensions." msgstr "" msgid "Return this array from your export hook instead of ``NULL``:" msgstr "" msgid "" "PyMODEXPORT_FUNC\n" "PyModExport_spam(void)\n" "{\n" " return spam_slots;\n" "}" msgstr "" msgid "Now, recompile and try it out:" msgstr "" msgid "" ">>> import spam\n" ">>> print(spam)\n" "<module 'spam' from '/home/encukou/dev/cpython/spam.so'>" msgstr "" msgid "You have an extension module! Try ``help(spam)`` to see the docstring." msgstr "" msgid "The next step will be adding a function." msgstr "" msgid "Exposing a function" msgstr "" msgid "" "To expose the :c:func:`system` C function directly to Python, we'll need to " "write a layer of glue code to convert arguments from Python objects to C " "values, and the C return value back to Python." msgstr "" msgid "" "One of the simplest ways to write glue code is a \":c:data:`METH_O`\" " "function, which takes two Python objects and returns one. All Python objects " "-- regardless of the Python type -- are represented in C as pointers to " "the :c:type:`PyObject` structure." msgstr "" msgid "Add such a function above the slots array::" msgstr "" msgid "" "static PyObject *\n" "spam_system(PyObject *self, PyObject *arg)\n" "{\n" " Py_RETURN_NONE;\n" "}" msgstr "" msgid "" "For now, we ignore the arguments, and use the :c:macro:`Py_RETURN_NONE` " "macro, which expands to a ``return`` statement that properly returns a " "Python :py:data:`None` object." msgstr "" msgid "" "Recompile your extension to make sure you don't have syntax errors. We " "haven't yet added ``spam_system`` to the module, so you might get a warning " "that ``spam_system`` is unused." msgstr "" msgid "Method definitions" msgstr "" msgid "" "To expose the C function to Python, you will need to provide several pieces " "of information in a structure called :c:type:`PyMethodDef` [#why-" "pymethoddef]_:" msgstr "" msgid "``ml_name``: the name of the Python function;" msgstr "" msgid "``ml_doc``: a docstring;" msgstr "" msgid "``ml_meth``: the C function to be called; and" msgstr "" msgid "" "``ml_flags``: a set of flags describing details like how Python arguments " "are passed to the C function. We'll use :c:data:`METH_O` here -- the flag " "that matches our ``spam_system`` function's signature." msgstr "" msgid "" "Because modules typically create several functions, these definitions need " "to be collected in an array, with a zero-filled sentinel at the end. Add " "this array just below the ``spam_system`` function:" msgstr "" msgid "" "\n" "static PyMethodDef spam_methods[] = {\n" " {\n" " .ml_name=\"system\",\n" " .ml_meth=spam_system,\n" " .ml_flags=METH_O,\n" " .ml_doc=\"Execute a shell command.\",\n" " },\n" " {NULL, NULL, 0, NULL} /* Sentinel */\n" "};\n" "\n" msgstr "" msgid "" "As with module slots, a zero-filled sentinel marks the end of the array." msgstr "" msgid "" "Next, we'll add the method to the module. Add a :c:data:`Py_mod_methods` " "slot to your :c:type:`PySlot` array:" msgstr "" msgid "" "\n" "PyABIInfo_VAR(abi_info);\n" "\n" "static PySlot spam_slots[] = {\n" " PySlot_STATIC_DATA(Py_mod_abi, &abi_info),\n" " PySlot_STATIC_DATA(Py_mod_name, \"spam\"),\n" " PySlot_STATIC_DATA(Py_mod_doc, \"A wonderful module with an example " "function\"),\n" " PySlot_STATIC_DATA(Py_mod_methods, spam_methods),\n" " PySlot_END\n" "};\n" "\n" msgstr "" msgid "" "Recompile your extension again, and test it. Be sure to restart the Python " "interpreter, so that ``import spam`` picks up the new version of the module." msgstr "" msgid "You should now be able to call the function:" msgstr "" msgid "" ">>> import spam\n" ">>> print(spam.system)\n" "<built-in function system>\n" ">>> print(spam.system('whoami'))\n" "None" msgstr "" msgid "" "Note that our ``spam.system`` does not yet run the ``whoami`` command; it " "only returns ``None``." msgstr "" msgid "" "Check that the function accepts exactly one argument, as specified by " "the :c:data:`METH_O` flag:" msgstr "" msgid "" ">>> print(spam.system('too', 'many', 'arguments'))\n" "Traceback (most recent call last):\n" " ...\n" "TypeError: spam.system() takes exactly one argument (3 given)" msgstr "" msgid "Returning an integer" msgstr "" msgid "" "Now, let's take a look at the return value. Instead of ``None``, we'll want " "``spam.system`` to return a number -- that is, a Python :py:type:`int` " "object. Eventually this will be the exit code of a system command, but let's " "start with a fixed value, say, ``3``." msgstr "" msgid "" "The Python C API provides a function to create a Python :py:type:`int` " "object from a C ``int`` value: :c:func:`PyLong_FromLong`. [#why-" "pylongfromlong]_" msgstr "" msgid "To call it, replace the ``Py_RETURN_NONE`` with the following 3 lines:" msgstr "" msgid "" "static PyObject *\n" "spam_system(PyObject *self, PyObject *arg)\n" "{\n" " int status = 3;\n" " PyObject *result = PyLong_FromLong(status);\n" " return result;\n" "}" msgstr "" msgid "" "Recompile, restart the Python interpreter again, and check that the function " "now returns 3:" msgstr "" msgid "" ">>> import spam\n" ">>> spam.system('whoami')\n" "3" msgstr "" msgid "Accepting a string" msgstr "" msgid "Finally, let's handle the function argument." msgstr "" msgid "" "Our C function, :c:func:`!spam_system`, takes two arguments. The first one, " "``PyObject *self``, will be set to the ``spam`` module object. This isn't " "useful in our case, so we'll ignore it." msgstr "" msgid "" "The other one, ``PyObject *arg``, will be set to the object that the user " "passed from Python. We expect that it should be a Python string. In order to " "use the information in it, we will need to convert it to a C value -- in " "this case, a C string (``const char *``)." msgstr "" msgid "" "There's a slight type mismatch here: Python's :py:class:`str` objects store " "Unicode text, but C strings are arrays of bytes. So, we'll need to *encode* " "the data, and we'll use the UTF-8 encoding for it. (UTF-8 might not always " "be correct for system commands, but it's what :py:meth:`str.encode` uses by " "default, and the C API has special support for it.)" msgstr "" msgid "" "The function to encode a Python string into a UTF-8 buffer is " "named :c:func:`PyUnicode_AsUTF8AndSize` [#why-pyunicodeasutf8]_. Call it " "like this:" msgstr "" msgid "" "static PyObject *\n" "spam_system(PyObject *self, PyObject *arg)\n" "{\n" " const char *command = PyUnicode_AsUTF8AndSize(arg, NULL);\n" " int status = 3;\n" " PyObject *result = PyLong_FromLong(status);\n" " return result;\n" "}" msgstr "" msgid "" "If :c:func:`PyUnicode_AsUTF8AndSize` is successful, *command* will point to " "the resulting C string -- a zero-terminated array of bytes [#embedded-nul]_. " "This buffer is managed by the *arg* object, which means we don't need to " "free it, but we must follow some rules:" msgstr "" msgid "" "We should only use the buffer inside the ``spam_system`` function. After " "``spam_system`` returns, *arg* and the buffer it manages might be garbage-" "collected." msgstr "" msgid "We must not modify it. This is why we use ``const``." msgstr "" msgid "" "If :c:func:`PyUnicode_AsUTF8AndSize` was *not* successful, it returns a " "``NULL`` pointer. When calling *any* Python C API, we always need to handle " "such error cases. The way to do this in general is left for later chapters " "of this documentation. For now, be assured that we are already handling " "errors from :c:func:`PyLong_FromLong` correctly." msgstr "" msgid "" "For the :c:func:`PyUnicode_AsUTF8AndSize` call, the correct way to handle " "errors is returning ``NULL`` from ``spam_system``. Add an ``if`` block for " "this:" msgstr "" msgid "" "static PyObject *\n" "spam_system(PyObject *self, PyObject *arg)\n" "{\n" " const char *command = PyUnicode_AsUTF8AndSize(arg, NULL);\n" " if (command == NULL) {\n" " return NULL;\n" " }\n" " int status = 3;\n" " PyObject *result = PyLong_FromLong(status);\n" " return result;\n" "}" msgstr "" msgid "" "To test that error handling works, compile again, restart Python so that " "``import spam`` picks up the new version of your module, and try passing a " "non-string value to your function:" msgstr "" msgid "" ">>> import spam\n" ">>> spam.system(3)\n" "Traceback (most recent call last):\n" " ...\n" "TypeError: bad argument type for built-in operation" msgstr "" msgid "" "Now, all that is left is calling the C library function :c:func:`system` " "with the ``char *`` buffer, and using its result instead of the ``3``:" msgstr "" msgid "" "static PyObject *\n" "spam_system(PyObject *self, PyObject *arg)\n" "{\n" " const char *command = PyUnicode_AsUTF8AndSize(arg, NULL);\n" " if (command == NULL) {\n" " return NULL;\n" " }\n" " int status = system(command);\n" " PyObject *result = PyLong_FromLong(status);\n" " return result;\n" "}" msgstr "" msgid "" "Compile your module, restart Python, and test. This time, you should see " "your username -- the output of the ``whoami`` system command:" msgstr "" msgid "" ">>> import spam\n" ">>> result = spam.system('whoami')\n" "User Name\n" ">>> result\n" "0" msgstr "" msgid "" "You can also test with other commands, like ``ls``, ``dir``, or one that " "doesn't exist:" msgstr "" msgid "" ">>> import spam\n" ">>> result = spam.system('nonexistent-command')\n" "sh: line 1: nonexistent-command: command not found\n" ">>> result\n" "32512" msgstr "" msgid "The result" msgstr "" msgid "" "Congratulations! You have written a complete Python C API extension module, " "and completed this tutorial!" msgstr "" msgid "Here is the entire source file, for your convenience:" msgstr "" msgid "" "/// Includes\n" "\n" "#include <Python.h>\n" "#include <stdlib.h> // for system()\n" "\n" "/// Implementation of spam.system\n" "\n" "static PyObject *\n" "spam_system(PyObject *self, PyObject *arg)\n" "{\n" " const char *command = PyUnicode_AsUTF8AndSize(arg, NULL);\n" " if (command == NULL) {\n" " return NULL;\n" " }\n" " int status = system(command);\n" " PyObject *result = PyLong_FromLong(status);\n" " return result;\n" "}\n" "\n" "/// Module method table\n" "\n" "static PyMethodDef spam_methods[] = {\n" " {\n" " .ml_name=\"system\",\n" " .ml_meth=spam_system,\n" " .ml_flags=METH_O,\n" " .ml_doc=\"Execute a shell command.\",\n" " },\n" " {NULL, NULL, 0, NULL} /* Sentinel */\n" "};\n" "\n" "/// Module slot table\n" "\n" "PyABIInfo_VAR(abi_info);\n" "\n" "static PySlot spam_slots[] = {\n" " PySlot_STATIC_DATA(Py_mod_abi, &abi_info),\n" " PySlot_STATIC_DATA(Py_mod_name, \"spam\"),\n" " PySlot_STATIC_DATA(Py_mod_doc, \"A wonderful module with an example " "function\"),\n" " PySlot_STATIC_DATA(Py_mod_methods, spam_methods),\n" " PySlot_END\n" "};\n" "\n" "/// Export hook prototype\n" "\n" "PyMODEXPORT_FUNC PyModExport_spam(void);\n" "\n" "/// Module export hook\n" "\n" "PyMODEXPORT_FUNC\n" "PyModExport_spam(void)\n" "{\n" " return spam_slots;\n" "}\n" msgstr "" msgid "Appendix: Other build tools" msgstr "" msgid "" "You should be able to follow this tutorial -- except the *Running your build " "tool* section itself -- with a build tool other than ``meson-python``." msgstr "" msgid "" "The Python Packaging User Guide has a `list of recommended tools <https://" "packaging.python.org/en/latest/guides/tool-recommendations/#build-backends-" "for-extension-modules>`_; be sure to choose one for the C language." msgstr "" msgid "Workaround for missing PyInit function" msgstr "" msgid "" "If your build tool output complains about missing ``PyInit_spam``, add the " "following function to your module for now:" msgstr "" msgid "" "// A workaround\n" "void *PyInit_spam(void) { return NULL; }" msgstr "" msgid "" "This is a shim for an old-style :ref:`initialization function <extension-" "export-hook>`, which was required in extension modules for CPython 3.14 and " "below. Current CPython does not need it, but some build tools may still " "assume that all extension modules need to define it." msgstr "" msgid "" "If you use this workaround, you will get the exception ``SystemError: " "initialization of spam failed without raising an exception`` instead of " "``ImportError: dynamic module does not define module export function``." msgstr "" msgid "Compiling directly" msgstr "" msgid "" "Using a third-party build tool is heavily recommended, as it will take care " "of various details of your platform and Python installation, of naming the " "resulting extension, and, later, of distributing your work." msgstr "" msgid "" "If you are building an extension for as *specific* system, or for yourself " "only, you might instead want to run your compiler directly. The way to do " "this is system-specific; be prepared for issues you will need to solve " "yourself." msgstr "" msgid "Linux" msgstr "" msgid "" "On Linux, the Python development package may include a ``python3-config`` " "command that prints out the required compiler flags. If you use it, check " "that it corresponds to the CPython interpreter you'll use to load the " "module. Then, start with the following command:" msgstr "" msgid "" "gcc --shared $(python3-config --cflags --ldflags) spammodule.c -o spam.so" msgstr "" msgid "" "This should generate a ``spam.so`` file that you need to put in a directory " "on :py:attr:`sys.path`." msgstr "" msgid "Footnotes" msgstr "" msgid "``spam`` is the favorite food of Monty Python fans..." msgstr "" msgid "" "The source file name is entirely up to you, though some tools can be picky " "about the ``.c`` extension. This tutorial uses the traditional ``*module.c`` " "suffix. Some people would just use :file:`spam.c` to implement a module " "named ``spam``, projects where Python isn't the primary language might use " "``py_spam.c``, and so on." msgstr "" msgid "" "Including :file:`stdlib.h` is technically not necessary, " "since :file:`Python.h` includes it and :ref:`several other standard headers " "<capi-system-includes>` for its own use or for backwards compatibility. " "However, it is good practice to explicitly include what you need." msgstr "" msgid "" "The :c:type:`!PyMethodDef` structure is also used to create methods of " "classes, so there's no separate \":c:type:`!PyFunctionDef`\"." msgstr "" msgid "" "The name :c:func:`PyLong_FromLong` might not seem obvious. ``PyLong`` refers " "to a the Python :py:class:`int`, which was originally called ``long``; the " "``FromLong`` refers to the C ``long`` (or ``long int``) type." msgstr "" msgid "" "Here, ``PyUnicode`` refers to the original name of the " "Python :py:class:`str` class: ``unicode``." msgstr "" msgid "" "The ``AndSize`` part of the name refers to the fact that this function can " "also retrieve the size of the buffer, using an output argument. We don't " "need this, so we set the second argument to NULL." msgstr "" msgid "" "We're ignoring the fact that Python strings can also contain NUL bytes, " "which terminate a C string. In other words, our function will treat " "``spam.system(\"foo\\0bar\")`` as ``spam.system(\"foo\")``. This possibility " "can lead to security issues, so the real ``os.system`` function size checks " "for this case and raises an error." msgstr "" |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |