Last active
April 28, 2021 07:18
-
-
Save shimarin/6576276e49522052e9c3 to your computer and use it in GitHub Desktop.
Goで Pythonを呼ぶ実験
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 同じ動作を Pythonで書くとこう。 | |
import platform | |
print platform.platform() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment