Selamlar. Bu yazıda go programlama dilinde oluşturduğumuz fonksiyonların nasıl shared object olarak export edileceğini ve Python ile kullanılacağını anlatacağım. (Görselleri hazırlarken Açık kaynak kodlu, özgür GIMP yazılımını kullanıyorum.)
Aslında bu yazı meraktan ibaret. Yani ne gibi bir paket geliştiriyorsunuz ki bunun Python’da bulunma zorunluluğu var ve dahası bu Python ile yapılamıyor. Neyse atomu parçalayan bir fonksiyon yazdığımızı varsayarak yola koyulalım. Adım adım gidelim ve öncelikle Go tarafında fonksiyonlarımızı oluşturalım.
Golang Fonksiyonların Oluşturulması
Yazıda geçecek örnek geometrik şekillerin hacmini hesaplayan bazı fonksiyonları içerecek. (Hepsini Python tarafına aktaracağımız için tek tek yazalım)
import "math" func KupunHacmi() float64 func DikdortgenlerPrizmasi() float64 func Kure() float64
Şimdi isterseniz modellemesi gerçekleşen bu metodları dolduralım. Öncelikle küpün hacmini veren metodla başlayalım. Bildiğiniz gibi küpün hacmi V=k^3 ile hesaplanır. Gerçeklemesini yapalım:
func Kup(k float64) float64 { return math.Pow(k, 3) }
Ardından dikdörtgenler prizmasının hacmini hesaplatalım. Bildiğinizi varsayarak a.b.c olduğunu belirtiyorum.
func DikdortgenlerPrizmasi(a float64, b float64, c float64) float64 { var v float64 = a*b*c return v }
Sıra geldi kürenin hacminin hesaplanmasına. Okul günlerine geri dönerek 4/3πr^3 olduğunu hatırlıyoruz. Bütün geometrik şekilleri yazmayacağım bu arada gereksiz. Şimdi bu son metodumuzu da yazalım.
func Kure(r float64) float64 { var b float64 = 4.0/3.0 var PI float64 = 3.14 var rKup float64 = math.Pow(r, 3) var v float64 = b * PI * rKup return v }
Artık metodlarımız hazır. Şimdi bu metodları C shared object olarak göstermemiz için C paketini import edip, metodların başına yorum satırlarıyla dışarı aktarılabilir olduklarını belirtmemiz gerekmekte. Örnek:
package main import ( "math" "C" ) //export Kup func Kup(k float64) float64 { return math.Pow(k, 3) } //export DikdortgenlerPrizmasi func DikdortgenlerPrizmasi(a float64, b float64, c float64) float64 { var v float64 = a*b*c return v } //export Kure func Kure(r float64) float64 { var b float64 = 4.0/3.0 var PI float64 = 3.14 var rKup float64 = math.Pow(r, 3) var v float64 = b * PI * rKup return v } func main() { }
Shared object yaratacak olsak bile main metodunun entry point olarak tanımlanması gerekiyor. Bir metodun export edilip edilemeyeceğine, metodun başında yer alan yorum satırları ile karar veriyoruz. Bu yorum satırında yer alan metod adı ayrıca Python tarafında çağırılacaktır.
İşlemlerimizi tamamladığımıza göre şu komutu konsoldan çalıştıralım:
go build -o geometri.so -buildmode=c-shared main.go
Bu komut kodları yazdığımız dosyadan (bende main.go) shared object dosyası oluşturmamıza yardımcı olacak. Bu işlemin ardından geometri.h ve geometri.so adında iki dosyanın oluşacak. İlgileniyorsanız C header file’a göz atabilirsiniz.
Python’a Shared Object Dosyasını Çağıralım
İşin golang tarafı bittiğine göre Python’a bu fonksiyonların nasıl aktarılacağı kalıyor. Öncelikle bilmiyorsanız söyleyeyim ctypes modülünü kullanacağız.
https://docs.python.org/3.6/library/ctypes.html adresinden modül hakkında bilgi alabilirsiniz.
Henüz Python kodlarını yazmaya başlamadan önce dilerseniz nm komutu yardımıyla object dosyasında oluşturduğumuz fonksiyonlar var mı kontrol edebiliriz. Bu arada bir fonksiyon bir metod diyorum özür dilerim bunun için. Ne diyorduk nm komutu şöyle bir komut ve çıktısı bizi beklemekte:
nm geometri.so | grep -e "T Kup" -e "T DikdortgenlerPrizmasi" -e "T Kure" 0000000000087260 T DikdortgenlerPrizmasi 00000000000871e0 T Kup 0000000000087300 T Kure
Demek ki bu object file, oluşturduğumuz fonksiyonları içeriyor. O halde artık kodlamaya geçelim:
from ctypes import * lib = cdll.LoadLibrary("/home/ali/Projects/go/gopy/geometri.so")
Görüldüğü gibi ctypes import edildi. Ardından LoadLibrary ile shared object dosyamızı referans olarak belirtiyoruz. Oluşturduğumuz lib dosyası artık geometri kütüphanesinin tüm olanaklarını yüklenmiş durumda.
argtypes: Go tarafında oluşturulan fonksiyonun, alacağı parametreler, tür karşılıklarıyla birlikte dizi türünden burada tanımlanır.
restype: Oluşturulan fonksiyon eğer tür dönüyorsa ctypes modülünde yer alan tür karşılığı belirtilir.
Her metod argstype ve restype özelliklerine sahip oluyor diyebiliriz.
Küp Metodu
Metod adı go dilinde oluşturduğumuz haliyle burada yer alacak ancak bazı önemli noktalar var. Örneğin bu metodun alacağı argüman türlerini belirtmemiz gerekiyor. Örneğin bu metod 5 parametre alsaydık tek tek burada da belirtmeliydik.
Python’da, Go dilinde bulunan float64 türü yok. Bu nedenden dolayı ctypes modülünde yer alan c_double tür dönüşümünü kullanıyoruz. Ayrıca go tarafında oluşturulan fonksiyonun dönüş türünü de belirtebiliyoruz.
lib.Kup.argtypes = [c_double] lib.Kup.restype = c_double print(lib.Kup(2))
Dikdörtgenler Prizması
Yukarıda yer alan argstype ve restype olayının en iyi kavranacağı nokta burası aslında.
lib.DikdortgenlerPrizmasi.argtypes = [c_double, c_double, c_double] lib.DikdortgenlerPrizmasi.restype = c_double print(lib.DikdortgenlerPrizmasi(2,3,4))
Küre
Artık bu kısmı anlatmaya gerek duymuyorum. Sonuç olarak nasıl kullanılacağını görmüş olduk.
lib.Kure.argtypes = [c_double] lib.Kure.restype = c_double print(lib.Kure(2))
Bu yazı bu kadar. Bu yazıda Go programlama dili ile oluşturulan shared object yani *.so dosyalarının Python’da nasıl kullanılacağını gördük.
Okuduğunuz için teşekkür ederim. İyi çalışmalar dilerim.