杰瑞科技汇

Python py buildvalue如何使用?

Of course! Let's break down Py_BuildValue in Python. This is a fundamental function in the Python C API, which is how you write C extensions to Python or embed Python within a C/C++ application.

Python py buildvalue如何使用?-图1
(图片来源网络,侵删)

What is Py_BuildValue?

In short, Py_BuildValue is a C function that creates a Python object (a tuple) from a set of C values.

Think of it as the C API equivalent of Python's built-in tuple() function, but with a powerful formatting string that tells it how to convert your C data into Python objects.

The "Value" in its name refers to the fact that it builds a single tuple containing all the values you provide.


The Core Concept: Format Strings

The magic of Py_BuildValue lies in its format string. This string is the first argument and it specifies the types and number of C variables that will follow.

Python py buildvalue如何使用?-图2
(图片来源网络,侵删)

Basic Format Characters

Here are the most common format characters you'll use:

Format Char C Type Python Object Created
s char * str
s# char *, int str (with length)
z char * (can be NULL) str or None
z# char *, int str (with length)
b char int
h short int
i int int
l long int
c char str (length 1)
d double float
f float float
O PyObject * A Python object (no conversion)
N PyObject * A Python object (steals reference)
S PyStringObject * str (must be a string)
... tuple

Important Notes:

  • s vs s#: Use s if your C string is null-terminated. Use s# if you want to pass a buffer and its explicit length, which is safer.
  • O vs N: This is crucial for memory management.
    • O: The PyObject* you pass must have its reference count incremented before the call (you own the reference). Py_BuildValue will decrement it when it's done.
    • N: This is a performance optimization. Py_BuildValue will "steal" the reference, meaning it will not decrement the reference count of the PyObject* you pass. You should use this when you have a new reference (e.g., from PyLong_FromLong) that you want Py_BuildValue to take ownership of.

Practical Examples (in C)

Let's imagine you're writing a C function that you want to call from Python. This function will return some data, and you'll use Py_BuildValue to package that data into a Python tuple.

Example 1: Returning a Simple Tuple of Integers

Let's say you have a C function that calculates a square and a cube.

Python py buildvalue如何使用?-图3
(图片来源网络,侵删)

C Code (my_module.c):

#include <Python.h>
// A C function that will be callable from Python
static PyObject* my_module_calculate(PyObject* self, PyObject* args) {
    long number;
    // Parse arguments from Python call: calculate(5)
    if (!PyArg_ParseTuple(args, "l", &number)) {
        return NULL; // Error already set
    }
    long square = number * number;
    long cube = number * number * number;
    // Use Py_BuildValue to create and return a Python tuple (square, cube)
    // "ll" means: long, long
    return Py_BuildValue("(ll)", square, cube);
}
// Module definition
static PyMethodDef MyModuleMethods[] = {
    {"calculate", my_module_calculate, METH_VARARGS, "Calculates the square and cube of a number."},
    {NULL, NULL, 0, NULL} // Sentinel
};
static struct PyModuleDef my_module = {
    PyModuleDef_HEAD_INIT,
    "my_module",
    NULL,
    -1,
    MyModuleMethods
};
PyMODINIT_FUNC PyInit_my_module(void) {
    return PyModule_Create(&my_module);
}

How to Compile and Run:

  1. Save the code as my_module.c.

  2. Compile it into a shared library (e.g., .so on Linux, .pyd on Windows).

    # On Linux/macOS
    gcc -shared -fPIC -I/usr/include/python3.x -o my_module.so my_module.c 
    # (replace python3.x with your version, e.g., python3.8)
  3. Use it in Python:

    import my_module
    result = my_module.calculate(5)
    print(result)        # Output: (25, 125)
    print(type(result))  # Output: <class 'tuple'>

Example 2: Returning a String and a Float

Here, we'll return a C string and a C double.

C Code:

#include <Python.h>
static PyObject* get_weather_data(PyObject* self, PyObject* args) {
    // No arguments to parse for this example
    const char* city = "London";
    double temperature = 15.5;
    // "sd" means: string (char*), double
    return Py_BuildValue("(sd)", city, temperature);
}
// ... (rest of the module definition is the same as above) ...

Python Usage:

import my_module
data = my_module.get_weather_data()
print(data)        # Output: ('London', 15.5)
print(type(data))  # Output: <class 'tuple'>

Example 3: Returning a Python Object and an Integer

This example shows how to pass a PyObject* into Py_BuildValue.

C Code:

#include <Python.h>
static PyObject* create_complex_object(PyObject* self, PyObject* args) {
    PyObject* py_list; // This will hold the Python list we create
    long id;
    // Parse arguments from Python call: create_complex_object([1, 2, 3], 123)
    if (!PyArg_ParseTuple(args, "Ol", &py_list, &id)) {
        return NULL;
    }
    // We must own a reference to py_list to pass it with 'O'.
    // PyArg_ParseTuple gives us a new reference, so we can use 'O'.
    // If we had created py_list ourselves with PyList_New, we would use 'N'.
    // "Ol" means: PyObject*, long
    return Py_BuildValue("(Ol)", py_list, id);
}
// ... (rest of the module definition is the same) ...

Python Usage:

import my_module
my_list = [1, 2, 3]
user_id = 123
result = my_module.create_complex_object(my_list, user_id)
print(result)        # Output: ([1, 2, 3], 123)
print(type(result))  # Output: <class 'tuple'>

Py_BuildValue vs. PyArg_ParseTuple

It's easy to confuse these two functions. They are opposites:

Feature Py_BuildValue PyArg_ParseTuple
Purpose Creates a Python tuple from C values. Parses Python arguments into C variables.
Direction C -> Python (Output from a C function) Python -> C (Input to a C function)
Format String Describes the C types to build the Python object. Describes the Python types to expect from the call.
Return Value A new PyObject* (the tuple) or NULL on error. 1 for success, 0 for error.

Analogy:

  • PyArg_ParseTuple: Like a customs officer reading your passport (Python args) and filling out a form (C variables).
  • Py_BuildValue: Like a packing robot taking items off a conveyor belt (C values) and wrapping them in a box (Python tuple).

Summary

Py_BuildValue is an essential tool in the Python C API. Its primary jobs are:

  1. To return complex data from a C extension function back to Python by packaging it into a tuple.
  2. To create Python objects from simple C types like `
分享:
扫描分享到社交APP
上一篇
下一篇