PythonとD

こんにちは、Habr!



ここでは、言語の長所と短所については説明しません。







それらを一緒に使用します!







素晴らしいpydライブラリがこれを助けてくれます。 その助けを借りて、dコードからpythonコードを呼び出すことも、その逆も可能です。



最初のオプションを検討してください。 dub.jsonファイルに入力します。



{ "name": "pydtest", "targetType": "executable", "dependencies": { "pyd": "~>0.9.7" }, "subConfigurations": { "pyd": "python34" } }
      
      





subConfigurationsは、Python 3.4を使用することを示します



source / main.dを作成します。



 import std.stdio; import pyd.pyd, pyd.embedded; void main() { py_init(); auto script = new InterpContext; //  2        //        myscript.py   script.py_stmts( "import sys" ); script.py_stmts( "sys.path.append('.')" ); script.py_stmts( "import myscript" ); writeln( script.py_eval!string( "myscript.func()" ) ~ " from pyd" ); }
      
      





myscript.pyを作成します

 def func(): return "hello habr!"
      
      





アセンブリとその結果を開始します

 dub build && ./pydtest
      
      





それだけです!

 hello habr! from pyd
      
      





すべてがとてもシンプルです!



少し複雑にしてみましょう。 myscript.pyに数字を追加する機能を追加します。



 def sum(a,b): return a + b
      
      





Dのコードから呼び出します。これをmain.main関数に追加します。



 ... script.x = 13; script.y = 21; writefln( "result: %d", script.py_eval!int( "myscript.sum(x,y)" ) ); ...
      
      





複雑に失敗しました。



InterpContextクラスはインタープリターのコンテキストを表し(奇妙なことに)、そのような簡単な方法で変数を追加できます。 フィールドxとyはスクリプトオブジェクトの一部ではありません-そのようなフィールドはありませんが、D言語ではクラス(または構造体)の存在しないメソッドへの呼び出しをopDispatchメソッドへの呼び出しに変換できるため、これは機能します。



InterpContext.opDispatchメソッドコード
  @property PydObject opDispatch(string id)() { //     return this.locals[id]; } @property void opDispatch(string id, T)(T t) { //     static if(is(T == PydObject)) { alias ts; }else{ PydObject s = py(t); } this.locals[id] = py(s); }
      
      







同様に、コンテキストからオブジェクトを取得できます。



 ... script.py_stmts( "z = myscript.sum(8,7)" ); writefln( "result2: %d", script.z.to_d!int ); ...
      
      





そして、ほぼ同じ方法で関数を呼び出すことができます:



 ... auto sum = script.myscript.sum; writefln( "result3: %d", sum(14,15).to_d!int ); ...
      
      





いくつかのポイント
D言語のプロパティ構文は長い間議論されトピックであり、具体的には、プロパティがopCallメソッドでオブジェクトを返すときの状況に関連しています。



 script.myscript.sum(14,15).to_d!int; // ,  ,     script.myscript.oneargfunc(12).to_d!int; //  ,   oneargfunc(12)   opDispatch   12 script.myscript.oneargfunc()(12).to_d!int; //    :   oneargfunc(),     opCall(12)
      
      







次に、Pythonコードから別の方法でDのコードを呼び出してみましょう。このための新しいフォルダーを作成します。

内容を含むdcode.dファイルを作成します。



 module dcode; import pyd.pyd; import std.math; float[] calc( float x, float y ) { return [ sqrt(x*y), x^^y, x/y ]; } extern(C) void PydMain() { def!(calc)(); module_init(); }
      
      





そして、setup_my_dcode.pyファイル(名前は影響しません):



 from pyd.support import setup, Extension projName = 'dcode' setup( name=projName, version='0.1', ext_modules=[ Extension(projName, ['dcode.d'], extra_compile_args=['-w'], build_deimos=True, d_lump=True ) ], )
      
      





拡張機能をビルドしましょう(テストファイルでシステムを詰まらせないように、インストールではなくビルドします)。



 python3 setup_my_dcode.py build
      
      





そのようなコンテンツのパパビルドを作成する

 build ├── lib.linux-x86_64-3.4 │  └── dcode.cpython-34m.so └── temp.linux-x86_64-3.4 └── infra ├── pydmain.d ├── so_ctor.o └── temp.o
      
      





build / lib.linux-x86_64-3.4 / dcode.cpython-34m.soに興味があります。 これを現在のディレクトリにコピーするか、それを含むフォルダーに移動し、インタラクティブインタープリターで直接確認できます。



 python3 Python 3.4.1 (default, Nov 3 2014, 14:38:10) [GCC 4.9.1 20140930 (Red Hat 4.9.1-11)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import dcode >>> dcode.calc( 5, 12 ) [7.745966911315918, 244140624.0, 0.4166666567325592] >>>
      
      





また、すべてが非常に簡単です!



そして再び、すべてを複雑にしてみましょう-クラスをdcode.dに追加します:



 class Foo { float a = 0, b = 0; static string desc() { return "some ops"; } this( float A, float B ) { a = A; b = B; } float sum() const { return a + b; } float div() const { return a / b; } } extern(C) void PydMain() { def!(calc)(); //   module_init(); //    wrap_class!( //    Foo, Init!(float,float), Repr!(Foo.toString), //  python      Def!(Foo.sum), Def!(Foo.div), StaticDef!(Foo.desc) )(); }
      
      





残念ながら、この状況では、事態は少し複雑になりました。 PythonでDクラスを使用するには、コンストラクター、関数などを宣言する必要があります。



収集、確認:



 python3 Python 3.4.1 (default, Nov 3 2014, 14:38:10) [GCC 4.9.1 20140930 (Red Hat 4.9.1-11)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from dcode import Foo >>> Foo.desc() 'some ops' >>> a = Foo(1,2) >>> a.div() 0.5 >>> a.sum() 3.0 >>>
      
      





うまくいく!



アプリケーションのオプションについて話す必要はありません。多くのオプションがあり、興味深いものです。 ライブラリがまだ安定バージョン1.0.0に達していないため、エラーが発生する可能性があることに注意してください。



私は1つの問題だけを見つけました:Dコードに埋め込まれたPythonコードからDコードを実行することはできません:







しかし、これは根本的な問題ではなく、著者が簡単に修正できるように思えます。



非常に素晴らしいプロジェクトのドキュメントがここにあり、他の例がここにあります



All Articles