2015-01-12 6 views
0

새로운 장난감 인 JCC 2.21을 가지고 놀고 있으며 파이썬 스크립트에서 콜백을 구현하는 데 문제가 있습니다. 다음 간단한 자바 스레드 API 래핑 된 및 파이썬 2.7 (CPython)에서 호출하고 있지만 JccTest.addJccTestListener(JccTestListener) 메서드를 호출 할 때 JVM null 인수를보고합니다.PyLucene JCC : Python으로 Java 인터페이스를 구현하고이를 통해 자바 스레드 콜백을 수신합니다.

import jcc_test 
import time, sys 

jcc_test.initVM(jcc_test.CLASSPATH) 

test = jcc_test.JccTest() 


class MyListener(jcc_test.JccTestListener): 
    def __init__(self): 
     pass 

    def message(self, msg): 
     print msg 

test.addJccTestListener(MyListener()) 
test.start() 
time.sleep(10) 
test.stop() 

sys.exit(0) 

결과 :

"python.exe" jcc_test_test.py 
Traceback (most recent call last): 
    File "jcc_test_test.py", line 16, in <module> 
    test.addJccTestListener(MyListener()) 
jcc_test.JavaError: java.lang.IllegalArgumentException: argument must be non-null 
    Java stacktrace: 
java.lang.IllegalArgumentException: argument must be non-null 
    at com.example.jcc.JccTest.addJccTestListener(JccTest.java:32) 

python -m jcc --jar jcc-test.jar --python jcc_test --build --install 

그리고는 (JccTest의 주요 방법에 해당)이 스크립트를 실행 :로

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.atomic.AtomicBoolean; 

public class JccTest implements Runnable { 

    private final Object listenersLock = new Object(); 
    private final List<JccTestListener> listeners = new ArrayList<JccTestListener>(); 
    private final AtomicBoolean running = new AtomicBoolean(false); 
    private final AtomicBoolean finished = new AtomicBoolean(false); 

    public void start() { 
     if (running.compareAndSet(false, true)) {    
      new Thread(this).start(); 
     } 
    } 

    public void stop() { 
     finished.set(true); 
    } 

    public void addJccTestListener(JccTestListener l) { 
     if (l == null) { 
      throw new IllegalArgumentException("argument must be non-null"); 
     } 
     synchronized (listenersLock) { 
      listeners.add(l); 
     } 
    } 

    public void removeJccTestListener(JccTestListener l) { 
     synchronized (listenersLock) { 
      listeners.remove(l); 
     } 
    } 

    @Override 
    public void run() {  
     System.out.println("Start"); 

     while (!finished.get()) { 
      System.out.println("Notifiying listeners"); 
      synchronized (listenersLock) { 
       for (JccTestListener l : listeners) { 
        System.out.println("Notifiying " + String.valueOf(l)); 
        l.message("I'm giving you a message!"); 
       } 
      } 
      System.out.println("Sleeping"); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException ex) { 
       continue; 
      } 
     } 

     running.set(false); 
     System.out.println("Stop"); 
    } 

    public static void main(String[] args) throws InterruptedException { 
     JccTest test = new JccTest(); 
     test.addJccTestListener(new JccTestListener() { 

      @Override 
      public void message(String msg) { 
       // called from another thread 
       System.out.println(msg); 
      } 
     }); 
     test.start(); 
     Thread.sleep(10000); 
     test.stop(); 
    } 
} 

public interface JccTestListener { 
    public void message(String msg); 
} 

생성 랩퍼

null 리스너 인스턴스 외에도 CPython에서도 이와 같은 작업을 수행하고 있습니까? 그 구현에서 단 한 스레드가 파이썬 스크립트를 한 번에 실행할 수 있다는 것을 읽었습니다.이 스크립트는 (?) 나를 위해 문제가 될 수 있습니다. 자이 썬에서 이런 일을하는 것은 사소한 일이었다.

저는 다소 파이썬에 익숙하지 않으므로 친절하십시오.

답변

0

알아 냈어. 이 작업을 수행하려면 자바 클래스에 파이썬 확장을 정의해야한다. 자세한 절차는 JCC documentation (파이썬에서 Java 클래스 확장 기능 작성)에 설명되어 있으며 다소 간단합니다.

먼저 인터페이스를 구현하는 클래스를 코딩하고 JCC에서 인식 할 수있는 마법 마커를 추가하고 래퍼 생성기가 생성하는 것에 영향을줍니다.

public class JccTestListenerImpl implements JccTestListener { 

    // jcc specific 
    private long pythonObject; 

    public JccTestListenerImpl() {} 

    @Override 
    public void message(String msg) { 
     messageImpl(msg); 
    } 

    // jcc specific 
    public void pythonExtension(long pythonObject) { 
     this.pythonObject = pythonObject; 
    } 

    // jcc specific 
    public long pythonExtension() { 
     return this.pythonObject; 
    } 

    // jcc specific 
    @Override 
    public void finalize() throws Throwable { 
     pythonDecRef(); 
    } 

    // jcc specific 
    public native void pythonDecRef(); 

    public native void messageImpl(String msg); 

} 

마커는 내 의견으로 표시되며 파이썬에서 확장 될 모든 클래스에서 그대로 사용해야합니다. 내 구현은 인터페이스 메소드를 파이썬으로 확장되는 네이티브 구현 메소드에 위임합니다.

그런 다음 평소처럼 래퍼 생성 :

python -m jcc --jar jcc-test.jar --python jcc_test --build --install 

을 그리고 마지막으로 새로운 클래스의 파이썬 확장합니다. 콜백에서 오는 예상대로이 지금 작동

import jcc_test 
import time, sys 

jvm = jcc_test.initVM(jcc_test.CLASSPATH) 

test = jcc_test.JccTest() 


class MyListener(jcc_test.JccTestListenerImpl): 
    ## if you define a constructor here make sure to invoke super constructor 
    #def __init__(self): 
    # super(MyListener, self).__init__() 
    # pass 

    def messageImpl(self, msg): 
     print msg 


listener = MyListener() 
test.addJccTestListener(listener) 
test.start() 
time.sleep(10) 
test.stop() 

sys.exit(0) 

"python.exe" jcc_test_test.py 
Start 
Notifiying listeners 
Notifiying [email protected] 
I'm giving you a message! 
Sleeping 
Notifiying listeners 
Notifiying [email protected] 
I'm giving you a message! 
Sleeping 

Process finished with exit code 0