0Pricing
Python Academy · บทเรียน

cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C

ใช้ cffi เพื่อทำงานร่วมกับ C แบบเป็นธรรมชาติสำหรับ Python มากขึ้น พร้อมการประกาศ C แบบแทรกในโค้ด

cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C เป็นบทเรียน Python Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Python Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน

cffi คืออะไร

cffi (อินเทอร์เฟซฟังก์ชันภายนอกของ C) ช่วยให้คุณเรียกใช้โค้ด C จาก Python โดยใช้คำประกาศของ C แทนคลาสของ ctypes วิธีนี้มีรูปแบบเป็น Python มากกว่าและมักปลอดภัยกว่า

# pip install cffi
from cffi import FFI
ffi = FFI()

ffi.cdef("double sqrt(double x);")
libm = ffi.dlopen(None)   # current process
print(libm.sqrt(2.0))     # 1.4142...

โหมด ABI กับโหมด API

ffi.dlopen() เป็นโหมด ABI ซึ่งเรียกใช้ไลบรารีที่ใช้ร่วมกันที่มีอยู่แล้วขณะทำงาน ส่วนโหมด API จะคอมไพล์ตัวห่อหุ้ม C และทำงานได้เร็วกว่าและมีความทนทานมากกว่า

from cffi import FFI
ffi = FFI()

# ABI mode (no compile step):
ffi.cdef("int abs(int x);")
libc = ffi.dlopen("libc.so.6")  # Linux
print(libc.abs(-42))   # 42

การประกาศด้วย cdef

ใช้ ffi.cdef() เพื่อประกาศลายเซ็นฟังก์ชัน โครงสร้าง และ typedef ของ C ที่ต้องการใช้จาก Python

from cffi import FFI
ffi = FFI()

ffi.cdef("""
    typedef struct {
        double x;
        double y;
    } Point;

    double distance(Point a, Point b);
""")

# lib = ffi.dlopen("mylib.so")

การสร้างโครงสร้าง C

ใช้ ffi.new() เพื่อจัดสรรโครงสร้าง C และกำหนดฟิลด์ของโครงสร้างจาก Python

from cffi import FFI
ffi = FFI()

ffi.cdef("typedef struct { int x; int y; } Vec2;")
lib = ffi.dlopen(None)

v = ffi.new("Vec2 *")
v.x = 3
v.y = 4
print(v.x, v.y)   # 3 4

สตริงและบัฟเฟอร์

ใช้ ffi.new("char[]", n) สำหรับบัฟเฟอร์ที่แก้ไขได้ และใช้ ffi.string(ptr) เพื่อแปลงพอยน์เตอร์สตริง C เป็นไบต์ของ Python

from cffi import FFI
ffi = FFI()

buf = ffi.new("char[]", b"hello world")
print(ffi.string(buf))   # b"hello world"

# Mutable buffer for output:
out = ffi.new("char[128]")
# c_func(out, 128)  # fill the buffer
# result = ffi.string(out).decode()

โหมด API พร้อมการตรวจสอบ

โหมด API จะคอมไพล์โมดูลตัวห่อหุ้ม C ขนาดเล็กเพื่อความปลอดภัยของชนิดข้อมูลและประสิทธิภาพที่ดียิ่งขึ้น ใช้ ffi.set_source() และสร้างโมดูลแบบออฟไลน์

from cffi import FFI
ffi = FFI()

ffi.cdef("int add(int a, int b);")
ffi.set_source("_mylib",
    """
    int add(int a, int b) { return a + b; }
    """
)

# Build: python build_mylib.py
# from _mylib import ffi, lib
# print(lib.add(3, 4))   # 7

ฟังก์ชันเรียกกลับจาก C ไปยัง Python

ใช้ ffi.callback() เพื่อห่อฟังก์ชัน Python ให้เป็นพอยน์เตอร์ฟังก์ชัน C ซึ่งสามารถส่งให้ไลบรารี C ได้

from cffi import FFI
ffi = FFI()
ffi.cdef("typedef int (*compare_fn)(int, int);")

@ffi.callback("int(int, int)")
def compare(a, b):
    return a - b

# pass compare to a C sort function

การจัดการหน่วยความจำ

อ็อบเจ็กต์ที่จัดสรรด้วย ffi.new() จะอยู่ภายใต้การจัดการของ Python และถูกคืนพื้นที่โดยอัตโนมัติ ใช้ ffi.gc(ptr, destructor) เพื่อผูกตัวคืนพื้นที่แบบกำหนดเอง

from cffi import FFI
ffi = FFI()

# ptr freed when Python GC collects it:
buf = ffi.new("int[10]")
buf[0] = 42
print(buf[0])   # 42

# Custom destructor:
# ptr = ffi.gc(lib.alloc(), lib.free)

cffi กับ ctypes

cffi ใช้สตริงคำประกาศของ C ซึ่งเป็นธรรมชาติกว่าสำหรับนักพัฒนา C ขณะที่ ctypes ใช้คลาสของ Python โหมด API ของ cffi ทำงานได้เร็วกว่า ส่วน ctypes ไม่ต้องคอมไพล์

# ctypes approach:
import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.abs.restype = ctypes.c_int
libc.abs.argtypes = [ctypes.c_int]
print(libc.abs(-5))   # 5

# cffi approach:
from cffi import FFI; ffi = FFI()
ffi.cdef("int abs(int);")
lib = ffi.dlopen(None)
print(lib.abs(-5))    # 5

การใช้ cffi กับ NumPy

ส่งข้อมูลอาร์เรย์ NumPy ไปยัง C โดยตรงผ่าน cffi ด้วย ffi.cast() และพอยน์เตอร์ ctypes.data ของอาร์เรย์

import numpy as np
from cffi import FFI
ffi = FFI()

arr = np.array([1.0, 2.0, 3.0])
ptr = ffi.cast("double *", arr.ctypes.data)
# Now ptr can be passed to a C function expecting double*

การจัดการข้อผิดพลาดด้วย cffi

โดยทั่วไปฟังก์ชัน C จะส่งสัญญาณข้อผิดพลาดผ่านค่าที่ส่งคืน ให้ตรวจสอบค่าที่ส่งคืนและใช้ ffi.errno สำหรับรหัสข้อผิดพลาดของ POSIX

import errno as errno_mod
from cffi import FFI
ffi = FFI()
ffi.cdef("int open(const char *path, int flags);")
lib = ffi.dlopen(None)

fd = lib.open(b"/nonexistent", 0)
if fd == -1:
    err = ffi.errno
    raise OSError(err, "open failed")

ตรวจสอบอย่างรวดเร็ว

cffi ใช้วิธีใดในการประกาศลายเซ็นฟังก์ชัน C ที่ต้องการเรียกใช้

สรุป

cffi ใช้ ffi.cdef() เพื่อประกาศลายเซ็นของ C และใช้ ffi.dlopen() สำหรับการเรียกใช้ไลบรารีในโหมด ABI โหมด API จะคอมไพล์ตัวห่อหุ้มเพื่อประสิทธิภาพที่ดียิ่งขึ้น ใช้ ffi.new() สำหรับหน่วยความจำของ C และใช้ ffi.callback() สำหรับฟังก์ชันเรียกกลับจาก Python ไปยัง C

คำถามที่พบบ่อย

บทเรียน “cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Python Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C”

ใช้ cffi เพื่อทำงานร่วมกับ C แบบเป็นธรรมชาติสำหรับ Python มากขึ้น พร้อมการประกาศ C แบบแทรกในโค้ด คุณปฏิบัติ Python Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Python Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Python Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Python Academy นี้ได้ไหม

ได้ บทเรียน Python Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุผลที่ต้องใช้ส่วนขยาย C: กรณีใช้งานและข้อแลกเปลี่ยน
  2. ctypes: การเรียกใช้ไลบรารี C จาก Python
  3. cffi: อินเทอร์เฟซฟังก์ชันภายนอกของ C
  4. การเขียนโมดูลส่วนขยาย C ของ Python
← กลับไปที่ Python Academy