You’re the Expert!

pynfinity

Build mountain with each pebble 🧗

Topics | Stepping Stones

📚 Guides

🌍 Pebbles & Contributions

✍️ Write a Post
🐼 Pandas DataFrames
🐼 Pandas DataFrames
🔢 NumPy Arrays
🔢 NumPy Arrays
📉 Matplotlib Plotting
📉 Matplotlib Plotting
🔥 Seaborn Heatmaps
🔥 Seaborn Heatmaps
🤖 Scikit-Learn Linear Regression
🤖 Scikit-Learn Linear Regression
🧹 Data Cleaning with Dropna
🧹 Data Cleaning with Dropna
🔍 Exploratory Data Analysis (EDA)
🔍 Exploratory Data Analysis (EDA)
⏳ Time Series Resampling
⏳ Time Series Resampling
🕸️ Web Scraping with BeautifulSoup
🕸️ Web Scraping with BeautifulSoup
🗄️ SQLAlchemy Basics
🗄️ SQLAlchemy Basics
📊 Interactive Plots with Plotly
📊 Interactive Plots with Plotly
📝 NLTK Tokenization
📝 NLTK Tokenization
🧠 TensorFlow Basics
🧠 TensorFlow Basics
🔥 PyTorch Tensors
🔥 PyTorch Tensors
📉 Statsmodels OLS
📉 Statsmodels OLS
📸 OpenCV Image Reading
📸 OpenCV Image Reading
🕸️ NetworkX Graphs
🕸️ NetworkX Graphs
🗺️ Folium Maps
🗺️ Folium Maps
🚀 Streamlit Apps
🚀 Streamlit Apps
⚡ FastAPI Endpoints
⚡ FastAPI Endpoints
✨ Jupyter Magic Commands
✨ Jupyter Magic Commands
📦 Virtual Environments
📦 Virtual Environments
🌲 Git Basics
🌲 Git Basics
🐳 Dockerfiles
🐳 Dockerfiles
☁️ AWS S3 with Boto3
☁️ AWS S3 with Boto3
🧩 Regular Expressions
🧩 Regular Expressions
λ Lambda Functions
λ Lambda Functions
📜 List Comprehensions
📜 List Comprehensions
⚡ Generators
⚡ Generators
🎀 Decorators
🎀 Decorators
🚪 Context Managers
🚪 Context Managers
🧵 Multithreading
🧵 Multithreading
🎛️ Multiprocessing
🎛️ Multiprocessing
⏳ AsyncIO
⏳ AsyncIO
🏷️ Type Hinting
🏷️ Type Hinting
📦 Dataclasses
📦 Dataclasses
🛡️ Pydantic Models
🛡️ Pydantic Models
🧪 Pytest Testing
🧪 Pytest Testing
🪵 Logging
🪵 Logging
💻 Argparse CLI
💻 Argparse CLI
📄 JSON Handling
📄 JSON Handling
📊 CSV Processing
📊 CSV Processing
🥒 Pickle Serialization
🥒 Pickle Serialization
🖥️ OS Module
🖥️ OS Module
⚙️ Sys Module
⚙️ Sys Module
📚 Collections Module
📚 Collections Module
🔁 Itertools
🔁 Itertools
🛠️ Functools
🛠️ Functools
➗ Math Module
➗ Math Module
+ New Post

🔌 Python C Extensions

Writing C extensions allows you to extend Python with compiled C code. This is useful for performance-critical sections or for interfacing with existing C libraries.


🧠 The Python/C API

Python provides a C API (Python.h) to interact with the Python interpreter.


🛠 Anatomy of a C Extension

A basic C extension involves:
1. Including Python.h.
2. Writing the C function.
3. Defining the method table.
4. Defining the module definition structure.
5. Initializing the module.

example.c

#include <Python.h>

// 1. The C function
static PyObject* method_fputs(PyObject* self, PyObject* args) {
    char* str;
    char* filename = NULL;
    int bytes_copied = -1;

    // Parse arguments
    if (!PyArg_ParseTuple(args, "ss", &str, &filename)) {
        return NULL;
    }

    FILE* fp = fopen(filename, "w");
    bytes_copied = fputs(str, fp);
    fclose(fp);

    return PyLong_FromLong(bytes_copied);
}

// 2. Method Table
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};

// 3. Module Definition
static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};

// 4. Module Initialization
PyMODINIT_FUNC PyInit_fputs(void) {
    return PyModule_Create(&fputsmodule);
}

🏗 Building the Extension

Use setuptools to build.

setup.py

from setuptools import setup, Extension

module = Extension('fputs', sources=['example.c'])

setup(
    name='Fputs',
    version='1.0',
    description='Python interface for fputs C library function',
    ext_modules=[module]
)

Build: python setup.py build_ext --inplace


🧩 Reference Counting

One of the most critical aspects of C extensions is managing reference counts.

  • Py_INCREF(obj): Increment reference count.
  • Py_DECREF(obj): Decrement reference count.

If you mess this up, you get memory leaks or segmentation faults.


📝 Summary

  • Low Level: Gives you full control but requires manual memory management.
  • Performance: Maximum performance possible.
  • Complexity: Harder to write and maintain than Cython.
  • GIL: You must be aware of the GIL and release it for long-running C operations if you want parallelism.

Created with ❤️ by Pynfinity