Ali GÖREN Açık Kaynak, JavaScript, Python, .NET RSS

Golang Fonksiyonlarını Python'da Kullanmak

Etiketler: programming golang python

/images/posts/go_py.png

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.

My name is Yoda

Who Am I

24 Level insanım. Bana aşağıdan ulaşabilirsiniz.

Yorumlar