Special Report

หลักการเขียนโปรแกรมยุคใหม่ๆ ในช่วงหลังๆ มานี้นิยมที่จะลดการเขียนโปรแกรมส่วนใหญ่ในภาษาระดับต่ำๆ เช่นภาษา C/C++ เนื่องจากเสี่ยงต่อการมีบั๊กค่อนข้างมาก และการพัฒนาที่ช้า เพื่อความเร็วในการพัฒนาแล้ว จึงมักนิยมใช้การพัฒนาในภาษาระดับสูงๆ เช่น Python, Ruby, PHP ฯลฯ แล้วทดสอบประสิทธิภาพ หากมีส่วนไหนทำงานช้าเกินยอมรับได้ จึงลงมือพัฒนาส่วนนั้นๆ เป็นภาษา C/C++ เพื่อความเร็ว แล้วจึงสร้างอินเทอร์เฟช เพื่อโมดูล C/C++ นั้นเข้ากับโปรแกรมหลัก

ปัญหาคือการเรียนรู้ และการเขียนโค้ดเพื่อเชื่อมต่อโมดูลต่างๆ เข้ากับภาษาระดับสูงนั้นเป็นงานที่สิ้นเปลืองพลังงานไม่ใช่น้อย และส่วนใหญ่กลับเป็นงานที่ต้องทำซ้ำไปมา สร้างความน่าเบื่อหน่าย ทางเลือกที่ดีกว่าคือการใช้โปรแกรมสร้างอินเทอร์เฟซอัตโนมัติ เช่น SWIG เพื่อทำงานส่วนที่น่าเบื่อทั้งหลายแทนที่เรา โดยใช้การคอนฟิกค่าเพียงเล็กน้อย

บทความนี้จะสมมติเหตุการณ์ที่เราต้องการสร้างฟังก์ชั่นที่เราทำเองฟังก์ชั่นหนึ่งที่ชื่อว่า toInt ที่แปลงค่าจากสตริงมาเป็นค่าเลขจำนวนเต็ม โดยในบทความจะถือว่าผู้อ่านมี Cygwin และ Python Win32 อยู่ในเครื่องอยู่ก่อนแล้ว


int toInt(char *s){
return atoi(s);
}

ก่อนอื่นที่เราต้องการคือโปรแกรม SWIG (ดาวน์โหลดที่นี่) หรืออาจเลือกลงตอนลง Cygwin เลยก็ได้ ถึงตอนนี้ก็แอบดูกันก่อนว่าเราจะเขียนให้ SWIG มันรู้จักฟัังก์ชั่นของเราได้ยังไง


%module example
%typemap(in) (char*s){
$1 = PyString_AsString($input);
}
%inline{
int toInt(char* s){
return atoi(s);
}
}

สั้นและง่ายอย่างไม่น่าเชื่อ โดยบรรทัดแรกนั้นคือชื่อโมดูลที่เราต้องการสร้าง ซึ่งจะไปมีผลเอาตอนที่เรา import เข้าโปรแกรม Python ของเรา

บรรทัดที่สองเป็น typemap ที่แปลงอาร์กิวเมนต์ข้ามภาษากัน ส่วนของ (in) นั้นคือระบุว่าเราต้องการสร้างส่วนแปลงข้อมูลอาร์กิวเมนต์ขาเข้าฟังก์ชั่นของเรา เนื่องจากฟังก์ชั่นของเราให้ค่าผลลัพธ์เป็น int ซึ่ง SWIG สามารถแปลงค่าได้เอง จึงไม่ต้องทำอะไรกับส่วนการส่งค่าออก (out) ส่วนต่อมาคือชื่อและ type ของฟังก์ชั่น ในกรณีนี้คือ (char*) ในกรณีที่เรามีฟังก์ชั่นที่ต้องการหลายอาร์กิวเมนต์ แต่สามารถแทนที่ได้ด้วยอาร์กิวเมนต์ในภาษา Python เพียงอาร์กิวเมนต์เดียว เราสามา่รถระบุได้ โดยการใส่หลา่ยอาร์กิวเมนต์ในวงเล็บ แบบเดียวกับการประกาศฟังก์ชั่นในภาษา C/C++

บรรทัดที่สามคือการประกาศการแปลงอาร์กิวเมนต์จากที่ได้รับมาจากภาษา Python โดยหนึ่งอาิร์กิวเมนต์ที่ได้รับจะมาในรูปของตัวแปรที่ชื่อว่า $input ซึ่งในส่วนนี้ SWIG จะนำสตริง $input ไปแปลงเป็นชื่อตัวแรกที่เป็น (PyObject *) ให้เอง ส่วน $1 นั้นหมายถึงอาร์กิวเมนต์ตัวแรกในรายการที่เราระบุ หากเรามีการใช้หลายอาร์กิวเมนต์ที่สร้างจาก อาร์กิวเมนต์ในภาษา Python เพีัยงหนึ่งอาร์กิวเมนต์ได้ เราก็อาจจะใช้ $2 หรือมากกว่านี้ขึ้นไปเรื่อยๆ ได้

ส่วนบรรทัดที่ 5 เรื่อยมานั้น คือการประกาศฟังก์ชั่นของเรา โดยการประกาศแบบ inline นั้นคือการประกาศทั้งฟังก์ชั่นมาอยู่ในไฟล์เดียวกัน แต่ถ้าต้องการใช้ฟังก์ชั่นจากไฟล์ภายนอกก็สามารถทำได้เช่นกัน

ถึงตอนนี้ ใ้ห้เราเซฟไฟล์นี้ในชื่อว่า example.i แล้วเรียก SWIG

swig -python example.i

เราจะได้ไฟล์ออกมาสองไฟล์คือ example_wrap.c และ example.py ต่อไปจะเป็นขั้นตอนการคอมไพล์

เนื่องจากเราต้องการใช้ Cygwin ในการคอมไพล์ทั้งหมด จึงทำให้เราไม่สามารถลิงก์เข้ากับ python24.dll ได้โดยตรง แต่ต้องการไฟล์ *.a ซึ่งคนใช้คอมไพล์เลอร์ตระกูล gcc คงคุ้นเคยกันดี

  1. เริ่มจากการก๊อปปี้ไฟล์ python24.dll จาก C:\Windows\system32 มาไว้ในที่ที่เราจะทำงาน
  2. ดาวน์โหลด pexports.exe มาไว้ในเครื่องให้พร้อม
  3. สั่ง pexports python22.dll > python22.def
  4. ใช้คำสั่ง dlltool ที่มีมาใน Cygwin เพื่อสร้าง libpython24.a ดังนี้ dlltool --dllname python24.dll --def python24.def --output-lib libpython24.a
  5. ถึงตอนนี้ก็ถึงเวลาคอมไพล์ โดยเริ่มจากการคอมไพล์ example_wrap.c ออกมาเป็น example_wrap.o ด้วยคำสั่ง gcc -c -mno-cygwin example_wrap.c -I/cygdrive/c/python24/include โดยการ สั่ง -mno-cygwin นั่นเพื่อให้ไฟล์ที่ออกมาใช้งานกับ dll ที่เป็น win32 native ได้ ส่วนการสั่ง -I ก็เพื่อดึงเอาไฟล์ header ของ Python ที่มาพร้อมอยู่ในตอนที่เราลง Python มาใช้งาน
  6. อย่าเพิ่งดีใจว่าเสร็จแล้ว เพราะเรายังไม่ได้ใช้ไฟล์ libpython24.a ที่เราสร้างขึ้นมา โดยการสั่ง gcc -shared -mno-cygwin example_wrap.o libpython24.a -o _example.dll โดยอาร์กิวเมนต์ -shared คือการสั่งให้ gcc สร้างไฟล์ dll นั่นเอง ส่วนการตั้งชื่อ dll ที่ได้นั้นสำคัญมากกว่าต้องตั้งชื่อเริ่มต้นด้วย underscore และตามด้วยชื่อโมดูลของเรา

เสร็จแล้ว!!! ในตอนนี้เราได้โค้ดที่เราเขียนในภาษาซีมาทำงาน ใน pyhton ได้ ดังตัวอย่าง


>>> import example
>>> example.toInt("10")
10

หากเราต้องการให้เรียกใช้โมดูลนี้ได้ไม่ว่าเราจะรัน Python จากที่ใดในเครื่อง ก็เพียงนำไฟล์ example.py และ _example.dll ไปวางไว้ในโฟลเดอร์ C:\Python24\Lib\site-packages เป็นอันเรียบร้อย

อ้างอิง

  1. sebsauvage.net : Writing C/C++ Python extensions without Microsoft Visual C++
  2. SWIG Document

Hiring! บริษัทที่น่าสนใจ

Carmen Software company cover
Carmen Software
Hotel Financial Solutions
Next Innovation (Thailand) Co., Ltd. company cover
Next Innovation (Thailand) Co., Ltd.
We are web design with consulting & engineering services driven the future stronger and flexibility.
KKP Dime company cover
KKP Dime
KKP Dime บริษัทในเครือเกียรตินาคินภัทร
Kiatnakin Phatra Financial Group company cover
Kiatnakin Phatra Financial Group
Financial Service
Fastwork Technologies company cover
Fastwork Technologies
Fastwork.co เว็บไซต์ที่รวบรวม ฟรีแลนซ์ มืออาชีพจากหลากหลายสายงานไว้ในที่เดียวกัน
Thoughtworks Thailand company cover
Thoughtworks Thailand
Thoughtworks เป็นบริษัทที่ปรึกษาด้านเทคโนโยลีระดับโลกที่คว้า Great Place to Work 3 ปีซ้อน
Iron Software company cover
Iron Software
Iron Software is an American company providing a suite of .NET libraries by engineer for engineers.
CLEVERSE company cover
CLEVERSE
Cleverse is a Venture Builder. Our team builds several tech companies.
Nipa Cloud company cover
Nipa Cloud
#1 OpenStack cloud provider in Thailand with our own data center and software platform.
Bangmod Enterprise company cover
Bangmod Enterprise
The leader in Cloud Server and Hosting in Thailand.
CIMB THAI Bank company cover
CIMB THAI Bank
MOVING FORWARD WITH YOU - CIMB is the leading ASEAN Bank
Bangkok Bank company cover
Bangkok Bank
Bangkok Bank is one of Southeast Asia's largest regional banks, a market leader in business banking
MuvMi (Urban Mobility Tech Co.,Ltd.) company cover
MuvMi (Urban Mobility Tech Co.,Ltd.)
Shape the future of urban mobility towards affordable, clean, and safe solutions
T.N. Digital Solution Co., Ltd. company cover
T.N. Digital Solution Co., Ltd.
TNDS has been involving in every first move of banking’s major digital transformation.
KBTG - KASIKORN Business-Technology Group company cover
KBTG - KASIKORN Business-Technology Group
KBTG - "The Technology Company for Digital Business Innovation"
Siam Commercial Bank Public Company Limited company cover
Siam Commercial Bank Public Company Limited
"Let's start a brighter career future together"
Icon Framework co.,Ltd. company cover
Icon Framework co.,Ltd.
Global Standard Platform for Real Estate แพลตฟอร์มสำหรับธุรกิจอสังหาริมทรัพย์ครบวงจร มาตรฐานระดับโลก
REFINITIV company cover
REFINITIV
The Financial and Risk business of Thomson Reuters is now Refinitiv
H LAB company cover
H LAB
Re-engineering healthcare systems through intelligent platforms and system design.
The Gang Technology Co., Ltd. company cover
The Gang Technology Co., Ltd.
We're a Digital Agency that helps our customers transform their business into digital with ease.
LTMH company cover
LTMH
LTMH มุ่งเน้นการพัฒนาผลิตภัณฑ์ที่สามารถช่วยพันธมิตรของเราให้บรรลุเป้าหมาย
Seven Peaks company cover
Seven Peaks
We Drive Digital Transformation
Wisesight (Thailand) Co., Ltd. company cover
Wisesight (Thailand) Co., Ltd.
The Best Choice For Handling Social Media · High Expertise in Social Data · Most Advanced and Secure
MOLOG Tech company cover
MOLOG Tech
We are Modern Logistic Platform, Specialize in WMS, OMS and TMS.
Data Wow Co.,Ltd company cover
Data Wow Co.,Ltd
We enable our clients to realize increased productivity by solving their most complex issues by Data
LINE Company Thailand company cover
LINE Company Thailand
LINE, the world's hottest mobile messaging platform, offers free text and voice messaging + Call
LINE MAN Wongnai company cover
LINE MAN Wongnai
Join our journey to becoming No.1 food platform in Thailand

chaba_bkk Tue, 13/06/2006 - 09:19

ผมไม่ได้ใช้ Python อ่ะ ใช้แต่ Java ไม่รู้ว่ามีตัวจัดการอย่างนี้ใช้รึเปล่า Let's play Ubuntu 5.10

lew Tue, 13/06/2006 - 17:01

chaba_bkk -SWIG ใช้กับ Java ได้ครับ แต่ผมใช้ไม่เป็น...

ผมก็เป็นแฟน python เหมือนกันครับ ส่วนมากผมใช้ pyrex (ซึ่งไม่ใช่ extension) ในการเพิ่มความเร็วให้ python แต่เจ้า SWIG นี่ยังไม่เคยลอง อ่านแล้วน่าสนใจครับ แน่นอนเลยครับว่าต้องลอง

(ขอบ่นหน่อยครับ) การคอมไพล์พวก extension บนวินโดวส์นี่ยากมากครับ เมื่อเทียบกับบน GNU/Linux ยิ่งไม่ได้ใช้ .NET Stupido ด้วยแล้ว มันร้องจะเอานู่นเอานี่เยอะเหลือเกิน กว่าจะคอมไพล์ผ่านนี่เสียเวลาไปหลายวันเลยครับ (เอ... หรือว่าเราโง่เองหว่า)

lew Wed, 14/06/2006 - 12:08

bow_der_kleine - ได้ยินชื่อ pyrex มานานเหมือนกันครับว่าเร็วกว่า SWIG พอตัวเลย แต่ผมเลือกใช้ SWIG เพราะดูเว็บแ้ล้วมันน่าเชื่อถือกว่า ระบบ Document อะไรต่างๆ ค่อนข้างเป็นรูปเป็นร่างกว่า แถมอ่านไว้ทีเดียวใช้กับภาษาอื่นได้ด้วยครับ

sake Sat, 21/05/2016 - 12:51

ctypes ไม่ต้อง compile

>>> import ctypes >>> toInt = ctypes.cdll.msvcrt.atoi >>> toInt("10") 10

Python 2.5 จะมี ctypes รวมมาด้วยเลย