49
Py + GI C 庫整合案 Derek

Py + gi 高效 c 庫整合方案

Embed Size (px)

Citation preview

Py + GI ⾼高效 C 庫整合⽅方案

Derek 呆

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

● Derek 呆 ○ [email protected] ○ [email protected]

● 來⾃自 Linux Deepin ● 慣 C ● 愛 Python ● 搞 BASH ● 編 Linux System Program

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

Python <= (Binding) => C

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

⼿手寫, 費時, 易出錯, 重複造輪

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

想⽤用⼯工具代勞?

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

試試 PyGObject

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

基於 GObject Introspection (GI)

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

與 Python 間只有少量整合代碼

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

⾃自源代碼⽣生成 Type Library

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

包含 Version, Function Signature, Type Information, ...

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

可於多語⾔言間共⽤用

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

Runtime 時配合 libffi 進⾏行調⽤用

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

易於將成果推送到 Upstream

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

準備⼯工作

$ apt-get install build-essential \ gobject-introspection \ python-gobject \ libglib2.0-dev \ gtk-doc-tools

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 1

/* mylib.h */ #ifndef __MYLIB_H_ #define __MYLIB_H_ void hello(); #endif /* __MYLIB_H_ */

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 1

/* mylib.c */ #include "mylib.h" #include <stdio.h> void hello() { printf("hello\n"); }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 1 $ gcc -o libmylib.so -share … $ g-ir-scanner -o MyLib-1.0.gir \

-lmylib \ -L. \ mylib.h …

$ g-ir-compiler MyLib-1.0.gir >MyLib-1.0.typelib

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 1 ... <namespace name="MyLib" version="1.0" shared-library="libmylib.so" c:identifier-prefixes="MyLib" c:symbol-prefixes="my_lib"> <function name="hello" c:identifier="hello"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> </function> </namespace> ...

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 1

$ python -c 'from gi.repository import MyLib; MyLib.hello()' hello

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

資源管理是 Binding 開發⼀一⼤大重點

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

否則 Resource Leaking, Double Free, Invalid FD, Bus Error, Segfault...

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 2

/* mylib.h */ #ifndef __MYLIB_H_ #define __MYLIB_H_ const char * hello3(); char * hello2(); #endif /* __MYLIB_H_ */

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 2 /* mylib.c */ #include "mylib.h" #include <stdio.h> #include <string.h> const char * hello3() { return "hello"; } char * hello2() { return strdup("hello"); }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 2 ... <function name="hello2" c:identifier="hello2"> <return-value transfer-ownership="full"> <type name="utf8" c:type="char*"/> </return-value> </function> <function name="hello3" c:identifier="hello3"> <return-value transfer-ownership="none"> <type name="utf8" c:type="const char*"/> </return-value> </function> ...

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 2

$ python -c 'from gi.repository import MyLib; print MyLib.hello2(); print MyLib.hello3()' hello hello

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

GI 有默認資源管理策略

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

但可通過 Annotation 改變

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 3

#ifndef __MYLIB_H_ #define __MYLIB_H_ /**

* hello4: * Returns: (transfer full): */ const char * hello4(); #endif /* __MYLIB_H_ */

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 3

#include "mylib.h" #include <stdio.h> const char * hello4() { return "hello"; }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 3

python -c 'from gi.repository import MyLib; print MyLib.hello4()' *** Error in `python': munmap_chunk(): invalid pointer: 0x00007f4503efd65d *** Aborted

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

Out 參數能處理嗎?

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 4

/** * hello5: * * @msg: (out callee-allocates): */ void hello5(char **msg);

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 4

void hello5(char **msg) { *msg = strdup("hello"); }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 4

$ python -c 'from gi.repository import MyLib; print MyLib.hello5()' hello

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

Out 參數會以 Return Value呈現

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

Struct ⼜又如何?

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

⼀一個 Type 需加上 4 個 Functions

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

基本也可以⼯工具產⽣生

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 5

#include <glib-object.h> #define TYPE_MY_OBJ (my_obj_get_type()) typedef struct _MyObj MyObj; MyObj my_obj_new(); GType my_obj_get_type();

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 5

struct _MyObj { int v; }; MyObj * my_obj_new() { return malloc(sizeof(MyObj)); }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 5

MyObj * _my_obj_copy(MyObj *self) { MyObj *new_self = my_obj_new(); *new_self = *self; return new_self; }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 5

void _my_obj_free(MyObj *self) { free(self); }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 5 GType my_obj_get_type() { static GType type = 0; if(! type) { type = g_boxed_type_register_static( "MyObj", (GBoxedCopyFunc) _my_obj_copy, (GBoxedFreeFunc) _my_obj_free); } return type; }

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

例 5

$ python >>> from gi.repository import MyLib >>> o = MyLib.MyObj() >>> o <MyObj at 0x27d39c0> >>> o.copy() <MyObj at 0x2a7b7e0> >>> o = None >>>

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

還有⽀支持不了的類型嗎?

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

Variadic Function

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

⼀一些資源

●  完整內容 ●  git repository ●  Annotation 參考

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!

廣告時間

●  Linux Deepin, 專注桌⾯面體驗的桌⾯面系統 ●  深之度公司⽂文化 ○  低調, 做好實事 ○  ⽀支持開源⼈人, 做想做的開源事 ○  週五 Hacking Day 讓你 Hack ⾃自我

●  總部位於武漢 ●  提供遠程⼯工作機會等你來挑戰

北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!