Vala到Python又回来了

时间:2013-04-18 11:23:48

标签: python c signals vala clutter

我很难尝试从Vala / C到Python的路径并再次退回。我所有的google-fu都引领着我。 我想使用Vala编写API,然后从Python(或者可能是Gnome Javascript)中使用它。

使用Clutter作为我的例子(也可能是GTK + 3小部件)这里是我的问题:我如何 -

去那里

编写一个自定义的Actor,点击后会:

  1. 更改颜色 - NB :这是在 Vala处理程序中完成的。即,vala对象连接到'按钮 - 释放'事件。该处理程序调用vala方法:this.set_col(' blue');
  2. 继续将该事件添加到Python中,还有一些数据 - 比如说我要打印"我变成了蓝色!" - 所以我需要"蓝色"作为一个字符串。
  3. 在Python中,我创建了一个舞台,并且(不知何故 - 通过GI魔术)创建了我的新Actor。我做所有Python的东西来设置它,我连接到相同的按钮释放'事件(我猜......)

    a)Vala处理程序运行然后运行Python吗? (按顺序,或者根本不用。)

    b)我是否必须在Vala处理程序中做一些特殊的事情 - 比如返回true,或者为Python发出一些新的信号来接收?

    再回来

    让我们说演员被称为V.我如何:V.set_col(' red')(在Python中)让它运行Vala set_col方法,传递Python字符串? (我怀疑这是GI下的自动化,但我不确定。)

    简而言之

    Vala actor -- event --> handler (in Vala) --> handler (in Python) with data
    Vala method <--- method call with args from Python 
    

    我也感谢任何链接,谢谢。

1 个答案:

答案 0 :(得分:1)

我明白了。下面的代码就像这样:

  1. 在目录中制作三个文件。
  2. &#34;建立&#34;是一个bash脚本。
  3. &#34; redsquare.vala&#34;是Vala,它将成为一个库(.so文件)
  4. &#34; test.py&#34;是使用该库的Python3代码。
  5. 安装这些:( apt-get bias,抱歉)
    • apt-get install libgirepository1.0-dev
    • apt-get install gobject-introspection
    • valac和公司
  6. 运行./build,它应该研磨voodoo并运行test.py文件。

  7. 您应该看到一个Clutter窗口。单击红色方块并观察控制台barf。

  8. : - d

    HTH。

    构建

    #!/bin/bash
    
    #
    # Script borrowed from Tal Liron at:
    # https://github.com/tliron/pygobject-example
    #
    # I did these to get this script to work:
    #
    # apt-get install libgirepository1.0-dev
    # apt-get install gobject-introspection
    #
    
    
    echo "Cleaning..."
    
    rm -rf tmp
    rm -rf lib
    rm -rf type
    rm -f test
    
    mkdir tmp
    mkdir lib
    mkdir type
    
        echo "Building Vala library..."
    
        # Note 1: Ubuntu package for valac: valac-0.14
        # Note 2: Generates broken gir if --gir= has a directory prefixed to it
        # Note 3: The -X switches for gcc are necessary!
        # Note 4: The generated gir will include GObject-2.0. That gir is
        #         included in Ubuntu package: libgirepository1.0-dev
    
        valac \
      --pkg clutter-1.0 \
        --library=Palelib \
        --directory=tmp \
        --gir=Palelib-1.0.gir \
        --output=libpalelib.so \
        -X -shared \
        -X -fPIC \
        redsquare.vala
    
        mv tmp/libpalelib.so lib
        mv tmp/Palelib-1.0.gir type
    
        # Note: We cannot generate C code and compile in the same call
        #       (We don't need the C code to run the test, but we are curious
        #       as to what Vala is generating. The resulting code will be in
        #       logging.c)
        #valac \
        #--ccode \
        #redsquare.vala
    
    
    echo "Building typelib..."
    
    # Note 1: Ubuntu package for g-ir-compiler: gobject-introspection
    # Note 2: The --shared-library switch is really only necessary when using
    #         the gir produced by valac, because it does not include the
    #         'shared-library' attribute in <namespace> tag.
    
    
    g-ir-compiler \
    --shared-library=libpalelib.so \
    --output=type/Palelib-1.0.typelib \
    type/Palelib-1.0.gir
    
    echo "Test Python..."
    
    # Note 1: Ubuntu's default path for typelib files seems to be:
    #         /usr/lib/girepository-1.0/.
    # Note 2: It is also possible to programmatically change the
    #         GI_TYPELIB_PATH environment var in Python (os.environ API).
    #         If you do so, make sure to set it before importing from
    #         gi.repository.
    LD_LIBRARY_PATH=lib \
    GI_TYPELIB_PATH=type \
    ./test.py
    

    redsquare.vala

    namespace Palelib {
    
        public class RedSquare : Clutter.Actor {
    
        //private vars
        private Clutter.Canvas _canvas;
        private int[] _col = { 255, 0, 0 };
    
        //Constructor - Needs to be called explicitly from Python by .new()
        public RedSquare() {
          stdout.printf( "RedSquare constructor.\n" );
    
          _canvas = new Clutter.Canvas();
          _canvas.set_size(300,300);
    
          this.set_size(300,300);
          this.set_content( _canvas );
    
          //Connect to the draw signal.
          _canvas.draw.connect(drawme);
    
          //Make it reactive and connect to the button-press-event
          this.set_reactive(true);
          this.button_press_event.connect( cleek );
        }
    
        //Button press signal handler
        private bool cleek ( Clutter.ButtonEvent evt ) {
          stdout.printf("Vala cleek() has run!\n");
          this._col = {0,255,0}; //Just change the colour
          this.redraw("from Vala");
          //return true; //Stops the signal here. Python won't get it.
          return false; //Lets the signal carry on going (to Python).
        }
    
        //Draws the Cairo art to the canvas
        private bool drawme( Cairo.Context ctx, int w, int h) {
          stdout.printf("drawme test.\n");
          ctx.set_source_rgb(this._col[0],this._col[1],this._col[2]);
          ctx.rectangle(0,0,300,300);
          ctx.fill();
          return true;
        }
    
        //Redraw - forces invalidate which trips the draw event
        //Am gonna call this directly from Python too!
        public void redraw(string? thing) {
          thing = thing ?? "from null"; //tests for null or else
          stdout.printf( "redraw test %s.\n", thing );
    
          this._canvas.invalidate();
        }
        } //end RedSquare class
    } //end namespace
    

    test.py

    #!/usr/bin/env python3
    
    """
    Tests the instance of our Vala actor.
    
    I expect to see a red square on the white stage.
    (It can be clicked.)
    
    """
    
    import sys
    from gi.repository import Palelib, Clutter
    
    Clutter.init(sys.argv)
    stage = Clutter.Stage()
    stage.set_size(800, 400)
    stage.set_title("Blah blah")
    stage.connect('destroy', lambda x: Clutter.main_quit() )
    
    
    # Make our Object:
    rs = Palelib.RedSquare.new() #Note the .new() call. Yuck.
    print(rs)
    #print(dir(rs)) # See that it is an Actor object.
    
    rs.set_position(100,100)
    
    stage.add_child(rs)
    
    #Force rs to appear. Calls a Vala method and passes a string.
    rs.redraw("from Python")
    
    """
    # Crud for testing:
    r1 = Clutter.Rectangle()
    r1.set_size(50,50)
    r1.set_position(0,0)
    damnweird = Clutter.Color.new(0,0,0,255)
    r1.set_color( damnweird  )
    
    stage.add_child(r1)
    """
    
    
    
    """
    Let's get an event going from Python!
    Because the RedSquare actor is *already* listening
    to a button-press-event (in Vala) this is the second 
    such event it will obey. 
    
    I *think* it happens after the vala cleek() method runs.
    If you |return true| in cleek(), then this does NOT run,
    so that implies that Python is happening second in the chain.
    """
    def gogo( a, evt ):
      print ("Hello from gogo. %s %s" % (a,evt))
    rs.connect("button_press_event", gogo)
    
    
    
    stage.show_all()
    Clutter.main()