آموزش برنامه نویسی C در برنامه نویسی پایتون ۳

2 سال پیش
آموزش برنامه نویسی C در برنامه نویسی پایتون 3

آموزش برنامه نویسی C در برنامه نویسی پایتون ۳

در این درس از مجموعه آموزش برنامه نویسی سایت سورس باران، به آموزش برنامه نویسی C در برنامه نویسی پایتون ۳ خواهیم پرداخت.

پیشنهاد ویژه : پکیج آموزش پایتون مختص بازار کار

هر کدی که با استفاده از هر زبان کامپایل شده ای مانند C++، C یا جاوا می نویسید، می تواند در اسکریپت پایتون دیگری ادغام یا وارد شود. این کد به عنوان یک “افزونه” در نظر گرفته می شود.

ماژول افزونه پایتون چیزی بیش از یک کتابخانه C معمولی نیست. در ماشین‌های یونیکس، این کتابخانه‌ها معمولا به .so ختم می‌شوند (برای شی مشترک). در ماشین های ویندوز، شما معمولا .dll را می بینید (برای کتابخانه های پیوندی پویا).

پیش نیازهای پسوند رایتینگ

برای شروع نوشتن پسوند خود، به فایل های هدر پایتون نیاز دارید.

  • در ماشین‌های یونیکس، معمولاً نیاز به نصب یک بسته مخصوص توسعه‌دهنده مانند python2.5-dev دارد.
  • کاربران ویندوز وقتی از نصب کننده پایتون باینری استفاده می کنند، این هدرها را به عنوان بخشی از بسته دریافت می کنند.

علاوه بر این، فرض بر این است که شما دانش خوبی از C یا ++C برای نوشتن هر افزونه پایتون با استفاده از برنامه نویسی C دارید.

 افزونه پایتون 

برای اولین نگاه خود به یک ماژول افزونه پایتون، باید کد خود را به چهار قسمت – گروه بندی کنید

  • فایل هدر Python.h.
  • توابع C که می خواهید به عنوان رابط ماژول خود در معرض نمایش قرار دهید.
  • جدولی که نام توابع شما را نقشه برداری می کند زیرا توسعه دهندگان پایتون آنها را به عنوان توابع C در داخل ماژول افزونه می بینند.
  • یک تابع مقداردهی اولیه

فایل هدر Python.h

شما باید فایل هدر Python.h را در فایل منبع C خود قرار دهید، که به شما امکان دسترسی به API داخلی پایتون را می دهد که برای اتصال ماژول به مفسر استفاده می شود.

مطمئن شوید که Python.h را قبل از هر هدر دیگری که ممکن است نیاز داشته باشید، قرار دهید. باید شامل توابعی که می خواهید از پایتون فراخوانی کنید دنبال کنید.

توابع C

امضای اجرای C توابع شما همیشه یکی از سه شکل زیر را دارد –

static PyObject *MyFunction( PyObject *self, PyObject *args );

static PyObject *MyFunctionWithKeywords(PyObject *self, PyObject *args, PyObject *kw);

static PyObject *MyFunctionWithNoArgs( PyObject *self );

 

هر یک از اعلان های قبلی یک شی پایتون را برمی گرداند. چیزی به نام تابع void در پایتون مانند C وجود ندارد. اگر نمی خواهید توابع شما مقداری را برگردانند، معادل C مقدار None پایتون را برگردانید. سرصفحه های پایتون یک ماکرو به نام Py_RETURN_NONE تعریف می کنند که این کار را برای ما انجام می دهد.

نام توابع C شما می تواند هر چیزی باشد که دوست دارید، زیرا هرگز خارج از ماژول افزونه دیده نمی شود. آنها به عنوان تابع استاتیک تعریف می شوند.

توابع C شما معمولاً با ترکیب ماژول پایتون و نام توابع با هم نامگذاری می شوند، همانطور که در اینجا نشان داده شده است –

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

 

این یک تابع پایتون به نام func در داخل ماژول است. شما نشانگرهای توابع C خود را در جدول متد ماژولی که معمولاً در کد منبع شما قرار می گیرد، قرار می دهید.

 روش جدول نگاشت

این جدول متد یک آرایه ساده از ساختارهای PyMethodDef است. این ساختار چیزی شبیه به این است –

struct PyMethodDef {
   char *ml_name;
   PyCFunction ml_meth;
   int ml_flags;
   char *ml_doc;
};

 

در اینجا توضیحات اعضای این ساختار آمده است

  • ml_name – این نام تابعی است که مفسر پایتون هنگام استفاده در برنامه‌های پایتون ارائه می‌کند.
  • ml_meth – این آدرس تابعی است که هر یک از امضاهای توضیح داده شده در بخش قبل را دارد.
  • ml_flags – این به مفسر می گوید که از کدام یک از سه امضا ml_meth استفاده می کند.
  • این پرچم معمولاً دارای مقدار METH_VARARGS است.
  • اگر می‌خواهید آرگومان‌های کلمه کلیدی را در تابع خود مجاز کنید، می‌توانید این پرچم را به صورت بیتی یا با METH_KEYWORDS یا به صورت بیتی اضافه کنید.
  • این همچنین می تواند مقدار METH_NOARGS داشته باشد که نشان می دهد شما نمی خواهید هیچ آرگومانی را بپذیرید.
  • ml_doc – این رشته مدرک برای تابع است که اگر تمایلی به نوشتن آن ندارید، می تواند NULL باشد.

این جدول باید با یک نگهبان که از مقادیر NULL و ۰ برای اعضای مناسب تشکیل شده است خاتمه یابد.

مثال

برای تابع تعریف شده در بالا، جدول نگاشت روش زیر را داریم

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};

 

تابع مقداردهی اولیه

آخرین بخش ماژول افزونه شما تابع مقداردهی اولیه است. این تابع زمانی که ماژول بارگذاری می شود توسط مفسر پایتون فراخوانی می شود. لازم است که تابع initModule نامیده شود، جایی که ماژول نام ماژول است.

تابع مقداردهی اولیه باید از کتابخانه ای که می خواهید بسازید صادر شود. سرصفحه‌های پایتون PyMODINIT_FUNC را به گونه‌ای تعریف می‌کنند که عبارت‌های مناسبی را برای محیط خاصی که در آن کامپایل می‌کنیم اتفاق بیفتد. تنها کاری که باید انجام دهید این است که هنگام تعریف تابع از آن استفاده کنید.

تابع اولیه سازی C شما به طور کلی ساختار کلی زیر را دارد –

PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}

 

 

در اینجا توضیحات تابع Py_InitModule3 – آمده است

  • func – این تابعی است که باید صادر شود.
  • module_methods – این نام جدول نگاشت تعریف شده در بالا است.
  • docstring – این نظری است که می خواهید در برنامه افزودنی خود بدهید.

با کنار هم قرار دادن همه اینها، به نظر می رسد زیر –

#include <Python.h>

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};

PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}

 

مثال

یک مثال ساده که از تمام مفاهیم فوق استفاده می کند –

#include <Python.h>

static PyObject* helloworld(PyObject* self)
{
   return Py_BuildValue("s", "Hello, Python extensions!!");
}

static char helloworld_docs[] =
   "helloworld( ): Any message you want to put here!!\n";

static PyMethodDef helloworld_funcs[] = {
   {"helloworld", (PyCFunction)helloworld, 
   METH_NOARGS, helloworld_docs},
   {NULL}
};

void inithelloworld(void)
{
   Py_InitModule3("helloworld", helloworld_funcs, "Extension module example!");
}

 

در اینجا از تابع Py_BuildValue برای ساخت یک مقدار پایتون استفاده می شود. کد بالا را در فایل hello.c ذخیره کنید. خواهیم دید که چگونه این ماژول را کامپایل و نصب کنیم تا از اسکریپت پایتون فراخوانی شود.

ساخت و نصب افزونه در پایتون

بسته distutils توزیع ماژول‌های پایتون، هم ماژول‌های پایتون خالص و هم ماژول‌های افزونه را به روشی استاندارد بسیار آسان می‌کند. ماژول ها به شکل منبع توزیع می شوند، از طریق یک اسکریپت راه اندازی که معمولاً setup.py as نامیده می شود، ساخته و نصب می شوند.

برای ماژول بالا، باید اسکریپت setup.py زیر را آماده کنید

from distutils.core import setup, Extension
setup(name = 'helloworld', version = '1.0',  \
   ext_modules = [Extension('helloworld', ['hello.c'])])

 

اکنون، از دستور زیر استفاده کنید، که تمام مراحل کامپایل و پیوند مورد نیاز را با دستورات و پرچم های کامپایلر و پیوند دهنده مناسب انجام می دهد و کتابخانه پویا حاصل را در یک دایرکتوری مناسب کپی می کند.

$ python setup.py install

 

در سیستم‌های مبتنی بر یونیکس، برای داشتن مجوز نوشتن در فهرست بسته‌های سایت، به احتمال زیاد باید این دستور را به صورت root اجرا کنید. این معمولاً در ویندوز مشکلی ندارد.

واردات افزونه

هنگامی که برنامه های افزونه خود را نصب کردید، می توانید آن افزونه را در اسکریپت پایتون خود به صورت زیر وارد کرده و فراخوانی کنید.

مثال

#!/usr/bin/python3
import helloworld

print helloworld.helloworld()

 

این نتیجه زیر را ایجاد می کند –

Hello, Python extensions!!

 

از آنجایی که به احتمال زیاد می خواهید توابعی را تعریف کنید که آرگومان ها را می پذیرند، می توانید از یکی از امضاهای دیگر برای توابع C خود استفاده کنید. به عنوان مثال، تابع زیر که تعدادی پارامتر را می پذیرد، به صورت زیر تعریف می شود

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Parse args and do something interesting here. */
   Py_RETURN_NONE;
}

 

جدول متد حاوی ورودی برای تابع جدید به شکل زیر است –

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { "func", module_func, METH_VARARGS, NULL },
   { NULL, NULL, 0, NULL }
};

 

می توانید از تابع API PyArg_ParseTuple برای استخراج آرگومان ها از یک اشاره گر PyObject که به تابع C شما ارسال شده است استفاده کنید.

اولین آرگومان PyArg_ParseTuple آرگومان args است. این شیئی است که شما تجزیه خواهید کرد. آرگومان دوم یک رشته قالب است که آرگومان ها را همانطور که انتظار دارید ظاهر شوند، توصیف می کند. هر آرگومان با یک یا چند کاراکتر در رشته قالب به صورت زیر نمایش داده می شود.

static PyObject *module_func(PyObject *self, PyObject *args) {
   int i;
   double d;
   char *s;

   if (!PyArg_ParseTuple(args, "ids", &i, &d, &s)) {
      return NULL;
   }
   
   /* Do something interesting here. */
   Py_RETURN_NONE;
}

 

خروجی

کامپایل کردن نسخه جدید ماژول و وارد کردن آن به شما امکان می دهد تابع جدید را با هر تعداد آرگومان از هر نوع فراخوانی کنید –

module.func(1, s = "three", d = 2.0)
module.func(i = 1, d = 2.0, s = "three")
module.func(s = "three", d = 2.0, i = 1)

 

احتمالاً می توانید تغییرات بیشتری را ارائه دهید.

تابع PyArg_ParseTuple

در اینجا امضای استاندارد برای تابع PyArg_ParseTuple – است

int PyArg_ParseTuple(PyObject* tuple,char* format,...)

 

این تابع برای خطاها ۰ و برای موفقیت مقداری برابر با ۰ نیست. Tuple PyObject* است که دومین آرگومان تابع C بود. در اینجا قالب یک رشته C است که آرگومان های اجباری و اختیاری را توصیف می کند.

در اینجا لیستی از کدهای قالب برای تابع PyArg_ParseTuple – آمده است

Code C type Meaning
c char رشته پایتون به طول ۱ تبدیل به char C می شود.
d double یک شناور پایتون به C double تبدیل می شود.
f float یک شناور پایتون به یک شناور C تبدیل می شود.
i int یک int پایتون به C int تبدیل می شود.
l long یک int پایتون به طول C تبدیل می شود.
L long long پایتون به long C تبدیل می شود
O PyObject*  ارجاع non-NULL به آرگومان پایتون دریافت می کند.
s char* رشته پایتون بدون تهی جاسازی شده به C char*
s# char*+int هر رشته پایتون به آدرس و طول C.
t# char*+int بافر تک قسمتی فقط خواندنی به آدرس و طول C.
u Py_UNICODE* یونیکد پایتون بدون تهی جاسازی شده به C.
u# Py_UNICODE*+int هر آدرس و طول Python Unicode C.
w# char*+int خواندن/نوشتن بافر تک بخش به آدرس و طول C.
z char* مانند s، None را نیز می پذیرد (C char* را روی NULL تنظیم می کند).
z# char*+int مانند s#، None را نیز می پذیرد (C char* را روی NULL قرار می دهد).
(…) as per … یک دنباله پایتون به عنوان یک آرگومان برای هر آیتم در نظر گرفته می شود.
| آرگومان های زیر اختیاری هستند.
: فرمت پایان، به دنبال آن نام تابع برای پیام های خطا.
; فرمت پایان، به دنبال آن کل متن پیام خطا.

مقادیر برگشتی

Py_BuildValue مانند PyArg_ParseTuple یک رشته فرمت می گیرد. به جای ارسال آدرس مقادیری که می سازید، مقادیر واقعی را وارد می کنید. در اینجا یک مثال نشان می دهد که چگونه یک تابع add – را پیاده سازی کنید

static PyObject *foo_add(PyObject *self, PyObject *args) {
   int a;
   int b;

   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("i", a + b);
}

 

اگر در پایتون پیاده سازی شود به این شکل خواهد بود

def add(a, b):
   return (a + b)

 

شما می توانید دو مقدار از تابع خود را به صورت زیر برگردانید. این با استفاده از یک لیست در پایتون گرفته می شود.

static PyObject *foo_add_subtract(PyObject *self, PyObject *args) {
   int a;
   int b;

   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("ii", a + b, a - b);
}

 

اگر در پایتون پیاده سازی شود به این شکل خواهد بود

def add_subtract(a, b):
   return (a + b, a - b)

 

تابع Py_BuildValue

در اینجا امضای استاندارد برای تابع Py_BuildValue – است

PyObject* Py_BuildValue(char* format,...)

 

در اینجا فرمت یک رشته C است که شی پایتون برای ساخت را توصیف می کند. آرگومان های زیر Py_BuildValue مقادیر C هستند که نتیجه از آنها ساخته شده است. نتیجه PyObject* یک مرجع جدید است.

جدول زیر رشته‌های کد رایج مورد استفاده را فهرست می‌کند که صفر یا تعداد بیشتری از آنها در قالب رشته‌ای به هم متصل شده‌اند.

Code C type Meaning
c char char C به یک رشته پایتون به طول ۱ تبدیل می شود.
d double یک double C تبدیل به شناور پایتون می شود.
f float یک شناور C تبدیل به شناور پایتون می شود.
i int یک C int تبدیل به یک int پایتون می شود.
l long C long تبدیل به int پایتون می شود.
N PyObject* یک شی پایتون را پاس می کند و یک مرجع را می دزدد.
O PyObject* یک شی پایتون را پاس می کند و آن را به صورت عادی INCRF می کند.
O& convert+void* تبدیل خودسرانه
s char* C 0 با char* به رشته پایتون خاتمه یافته یا NULL به None.
s# char*+int C char* و طول به رشته پایتون یا NULL به None.
u Py_UNICODE* رشته C-wide، تهی پایانه به Python Unicode یا NULL به None.
u# Py_UNICODE*+int رشته و طول C-wide به Python Unicode یا NULL به None.
w# char*+int خواندن/نوشتن بافر تک بخش به آدرس و طول C.
z char* مانند s، None را نیز می پذیرد (C char* را روی NULL تنظیم می کند).
z# char*+int مانند s#، None را نیز می پذیرد (C char* را روی NULL قرار می دهد).
(…) as per … تاپل پایتون را از مقادیر C می سازد.
[…] as per … لیست پایتون را از مقادیر C می سازد.
{…} as per … دیکشنری پایتون را از مقادیر C، کلیدها و مقادیر متناوب می‌سازد.

کد {…} از تعداد زوج مقادیر C، به طور متناوب کلیدها و مقادیر، فرهنگ لغت می سازد. برای مثال، Py_BuildValue(“{issi}”,23,”zig”,”zag”,42) دیکشنری مانند Python’s {23:’zig’,’zag’:42} را برمی‌گرداند.

 

منبع.

 

 

لیست جلسات قبل آموزش برنامه نوبسی پایتون ۳

  1. آموزش برنامه نویسی پایتون ۳
  2. آموزش موارد جدید در برنامه نویسی پایتون ۳
  3. آموزش مرور کلی برنامه نویسی پایتون ۳
  4. آموزش راه اندازی محیط برنامه نویسی پایتون ۳
  5. آموزش نحو در برنامه نویسی پایتون ۳
  6. آموزش انواع متغیرها در برنامه نویسی پایتون ۳
  7.  آموزش عملگرهای پایه در برنامه نویسی پایتون ۳
  8.  آموزش تصمیم گیری در برنامه نویسی پایتون ۳
  9.  آموزش حلقه ها در برنامه نویسی پایتون ۳
  10. آموزش اعداد در برنامه نویسی پایتون ۳
  11. آموزش رشته ها در برنامه نویسی پایتون ۳
  12.  آموزش لیست ها در برنامه نویسی پایتون ۳
  13.  آموزش تاپل ها در برنامه نویسی پایتون ۳
  14. آموزش دیکشنری در برنامه نویسی پایتون ۳
  15.  آموزش تاریخ و زمان در برنامه نویسی پایتون ۳
  16.  آموزش توابع در برنامه نویسی پایتون ۳
  17. آموزش ماژول ها در برنامه نویسی پایتون ۳
  18. آموزش فایل های ورودی/خروجی در برنامه نویسی پایتون ۳
  19. آموزش مدیریت استثنا در برنامه نویسی پایتون ۳
  20. آموزش شی گرایی در برنامه نویسی پایتون ۳
  21.  آموزش عبارات منظم در برنامه نویسی پایتون ۳
  22. آموزش CGI در برنامه نویسی پایتون ۳
  23.  آموزش دسترسی به پایگاه داده MySQL در برنامه نویسی پایتون ۳
  24.  آموزش برنامه نویسی شبکه در برنامه نویسی پایتون ۳
  25. آموزش ارسال ایمیل با استفاده از SMTP در برنامه نویسی پایتون ۳
  26.  آموزش برنامه نویسی چند رشته ای در برنامه نویسی پایتون ۳
  27. آموزش پردازش XML در برنامه نویسی پایتون ۳
  28. آموزش برنامه نویسی Tkinter در برنامه نویسی پایتون ۳
0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه