Skip to content

Instantly share code, notes, and snippets.

@shimarin
Last active April 28, 2021 07:18
Show Gist options
  • Save shimarin/6576276e49522052e9c3 to your computer and use it in GitHub Desktop.
Save shimarin/6576276e49522052e9c3 to your computer and use it in GitHub Desktop.
Goで Pythonを呼ぶ実験
/**
* Goから Pythonの関数を呼び出す実験
* 適当な文字列を返してくる手頃な関数 platform.platform() を呼んでみる。
* http://docs.python.jp/2/library/platform.html
*
* Cから Pythonを呼び出す方法
* http://docs.python.jp/2/extending/embedding.html
* が基本となる。Go -> C -> Pythonという呼び出しフローになるのでやや煩雑
*/
package main
// #include <Python.h>
// void __Py_DECREF(PyObject* obj) { Py_DECREF(obj); }
// #cgo CFLAGS: -I /usr/include/python2.7
// #cgo LDFLAGS: -lpython2.7
import "C"
// Makefileとか書かなくてもこのソースファイルを go build するだけでいい!楽ちん!
import (
"fmt"
"unsafe"
)
/**
* Pythonオブジェクトの参照カウンタを減らすマクロ Py_DECREFを呼ぶ。
* GoはCのヘッダに書いてあるマクロを呼べないので、そのマクロを呼ぶための適当な
* C関数を import "C"のコメントブロックに書いておいて、そちらを呼び出すようにする
*/
func Py_DECREF(obj *C.PyObject) {
C.__Py_DECREF(obj)
}
func main() {
// Pythonインタプリタの初期化
C.Py_Initialize()
/* モジュール platform をインポートする。
Cの関数に文字列を渡すには、C.CStringで Goの文字列から Cのnull-terminatedな
文字列を作る必要がある。 */
module_name := C.CString("platform")
module := C.PyImport_ImportModule(module_name)
/* C.CStringは mallocで文字列のためのメモリを確保する。それを freeで開放するのは
どうやらプログラマの責任のようである */
C.free(unsafe.Pointer(module_name))
// モジュール platformのアトリビュート platform を取得する。
function_name := C.CString("platform")
function := C.PyObject_GetAttrString(module, function_name)
C.free(unsafe.Pointer(function_name))
// そのアトリビュートが存在しており、
if function != nil {
// しかもそれが呼び出し可能なオブジェクト(つまり関数)なら呼び出して結果を表示する
if C.PyCallable_Check(function) > 0 {
args := C.PyTuple_New(0) // 引数はタプル。引数を取らない関数を呼び出すので長さゼロで。
// Pythonの関数を呼び出すための Cの関数を Goから呼び出す。ヒャッホー
retval := C.PyObject_CallObject(function, args)
Py_DECREF(args) // 引数として使ったタプルは関数から戻ればもう用無し
// C文字列をGoの文字列に変換するには C.GoStringを使う
fmt.Println(C.GoString(C.PyString_AsString(retval)))
// 関数の戻り値はもう表示してしまったので用無し
Py_DECREF(retval)
}
// platform関数はもう使い終わったので用無し
Py_DECREF(function)
}
// platformモジュールももう使い終わったので用無し
Py_DECREF(module)
// Pythonインタプリタを片付ける
C.Py_Finalize()
}
# 同じ動作を Pythonで書くとこう。
import platform
print platform.platform()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment