用Jython实现解释执行的Java类


用Jython可以实现预编译成Java字节流的Java类,需用Jythonc进行编译。
不过更方便的用法是直接用Jython实现嵌入式的类,不需要编译。
一方面是编译很麻烦,另一面预编译并没有带来速度上的优势。
Jythonc编译程序在Jython2.3版中将不再包含。

JDK6已经新增了脚本引擎,可以使用JavaScript,不过使用Jython脚本更令人激动。

本例jyinterface项目包含4个文件:
      -Main.java
      -EmployeeType.java       对象接口定义
      -Employee.py                   Python实现
      -EmployeeFactory.java   对象工厂,生成一个Java对象



// 
   EmployeeType.java 
  
 
  package 
   jyinterface.interfaces;

 
  public 
    
  interface 
   EmployeeType  
  ... 
  {
    public String getEmployeeFirst();
    public String getEmployeeLast();
    public String getEmployeeId();
}

用Jython实现解释执行的Java类_python

#  Employee.py


from 
   jyinterface.interfaces  
  import 
   EmployeeType

   class 
   Employee(EmployeeType):
      def 
    
  __init__ 
  (self, first, last, id):
      self.first    = 
   first
      self.last     = 
    last
      self.id    = 
   id

      def 
   getEmployeeFirst(self):
         return 
   self.first

      def 
   getEmployeeLast(self):
         return 
   self.last

      def 
   getEmployeeId(self):
         return 
   self.id
 

   
//    EmployeeFactory.java   
   package    jyinterface.factory;

   import    jyinterface.interfaces.EmployeeType;
   import    org.python.core.Py;
   import    org.python.core.PyObject;
   import    org.python.core.PyString;
   import    org.python.util.PythonInterpreter;

   public     
  class 
   EmployeeFactory  
  ... 
  {

    public EmployeeFactory() ...{
        PythonInterpreter interpreter = new PythonInterpreter();
        interpreter.exec("from Employee import Employee");
        jyEmployeeClass = interpreter.get("Employee");
    }

    public EmployeeType create(String first, String last, String id) ...{
        PyObject pyObj = jyEmployeeClass.__call__(new PyString(first),
            new PyString(last), new PyString(id));
        return (EmployeeType)pyObj.__tojava__(EmployeeType.class);
    }

    private PyObject jyEmployeeClass;
}   
 

注意:Employee.py必须在sys.path路径,这样才能导入。 

如将Employee.py放在运行目录,并在jython的registry文件中的python.path添加“.”。 

或直接放在jython的Lib目录下。 


   
//    Main.java   
   package    jyinterface;

   import    jyinterface.factory.EmployeeFactory;
   import    jyinterface.interfaces.EmployeeType;

   public       class 
   Main  
  ... 
  {

    private static void print(EmployeeType employee) ...{
        System.out.println("Name: " + employee.getEmployeeFirst() + " "
                + employee.getEmployeeLast());
        System.out.println("Id: " + employee.getEmployeeId());
    }

    public static void main(String[] args) ...{
        EmployeeFactory factory = new EmployeeFactory();
        print(factory.create("Josh", "Juneau", "1"));
        print(factory.create("Charlie", "Groves", "2"));
    }
}


参考:


[1] Accessing Jython from Java Without Using jythonc


[2] Simple and Efficient Jython Object Factories




[2]中会产生一个类型转换错误:


return (EmployeeType)jyEmployeeClass.__call__(...

PyObject应该不能直接转成java对象的,不知作者为什么会这样。



[1]使用execfile()来运行py文件,也可以转成exec("import " + module)


以避免每生成一个对象就运行一遍。


但是也有好处,即可以实时更改py文件立即生效。


而import的文件会缓存,必须显示调用reload()才会重新导入。



Python/C的内嵌接口中好像没有__tojava__()这样的函数,能在语言之间转换对象类型。


看上去只能处理PyObject对象.


(还在摸索中,用Python扩展C++接口应该可以实现。可能boost::python会有。)