अंतिम अद्यतन:2026-10-12
CPython extension development notes¶
यह लेख हाल में Apache को दिए गए एक feature की पृष्ठभूमि पर चलेगा, CPython में आई समस्याओं पर विस्तार से बात करेंगे, और खुद 0 से एक library लिखने की कोशिश करेंगे, code 星球 पर भी रखा जा चुका है, रुचि रखने वाले download करके सीख सकते हैं।
0. पृष्ठभूमि¶
हाल में apache arrow को दिया गया एक feature, C++ interface के बदलाव के कारण दूसरी भाषाओं के interfaces में भी बदलाव लाया, कुछ tests भी ठीक करने की ज़रूरत पड़ी।
PyArrow से परिचित लोगों के लिए यह कोई नई बात नहीं, इस बार के interface बदलाव में इस library को भी modify करना पड़ा, क्योंकि दोनों एक ही repository में हैं, वरना ci पास नहीं होता। और PyArrow का implementation CPython से हुआ है, पहले CPython खास नहीं सीखा था, इसलिए ढेर सारी समस्याएँ आईं, जिनमें दो समस्याएँ काफी ज़रूरी थीं, यहाँ note करता हूँ।
समस्या 1: Initialization function के अंदर दूसरी classes के default constructors समर्थित नहीं हैं।
उदाहरण:
Error:
TypeError: descriptor '_scalar' for 'pyarrow._compute.Expression' objects doesn't apply to a 'bool' object
देखा जा सकता है कि पहचान नहीं हुई, वास्तविक स्थिति में Expression._scalar(True) valid है, हम इसके अंदर का implementation देखते हैं:
@staticmethod
def _scalar(value):
cdef:
Scalar scalar
if isinstance(value, Scalar):
scalar = value
else:
scalar = lib.scalar(value)
return Expression.wrap(CMakeScalarExpression(scalar.unwrap()))
देखा जा सकता है कि अंदर सामान्य bool type समर्थित है, मुझे शक हुआ कि यह cpython की limitation है, इसलिए नीचे वाले तरीके में बदलने पर काम हो गया:
def __init__(self, mode="only_valid", filter=None):
if filter is None:
filter = Expression._scalar(True)
समस्या 2: Definition का order
जब मैंने बाद में बनाए _true का उपयोग किया, तो हर बार पास होने वाला default value खाली था, यह समझने में आसान है, क्योंकि अंत में compile होकर यह एक xxx.cpp फ़ाइल में translate होता है, C++ के नियमों के अनुसार पहले पढ़ा गया value स्वाभाविक रूप से खाली होता है।
def __init__(self, mode="only_valid", filter=_true):
pass
cdef CExpression _true = CMakeScalarExpression(
<shared_ptr[CScalar]> make_shared[CBooleanScalar](True)
)
ठीक है, ऊपर की पृष्ठभूमि के आधार पर, मैं भी खुद एक उदाहरण लिखना चाहता हूँ, जैसे: C++ से एक class लिखकर sort और sum wrap करें, फिर Python से call करें।
1. CPython का पूर्ण उदाहरण¶
- एक .h फ़ाइल बनाएँ
void sort(std::vector<int>& nums) {
std::sort(nums.begin(), nums.end());
}
int sum(std::vector<int>& nums) {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
}
2) foo.pyx बनाएँ
मुख्य बात: ऊपर वाले vector के लिए चाहिए:
फिर एक class define करके, C++ के interface को call करें।
cdef class PyFoo:
cdef Foo* f
def __cinit__(self):
self.f = new Foo()
def __dealloc__(self):
del self.f
def sort(self, nums):
cdef vector[int] c_nums = nums
self.f.sort(c_nums)
def sum(self, nums):
cdef vector[int] c_nums = nums
return self.f.sum(c_nums)
- setup.py फ़ाइल बनाएँ
ext = Extension('Foo', sources=["foo.pyx"], language="c++", include_dirs=[numpy.get_include()])
setup(name="Foo", ext_modules = cythonize([ext]))
- Run
अंत में, एक test script लिखकर अपना लिखा python interface उपयोग किया जा सकता है।
import Foo
f = Foo.PyFoo()
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
f.sort(nums)
print("Sorted nums:", nums)
print("Sum of nums:", f.sum(nums))
CPython कुछ projects में काफी उपयोग होता है, सीखना शुरू करें~
Run:
संबंधित विषय¶
- C++ string के छह split तरीके | C++那些事
- libcurl C++ development notes | C++那些事
- Open source C++ code कैसे पढ़ें | C++那些事
- एक दिलचस्प C++ code | C++那些事
- C++ loop के बिना 1-100 print करना | C++那些事