Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you write a Java class with ABCL?

Is there a way to create a Java class with ABCL (that extends another class)?

like image 614
compman Avatar asked Jan 24 '11 19:01

compman


1 Answers

One can write directly write a Java class as JVM bytecode via the functions in the JVM package which is the code that ABCL's own compiler uses. As of abcl-0.25.0, there is unsupported code for a JAVA:JNEW-RUNTIME-CLASS method which allows one to dynamically write a Java class that calls Lisp methods for execution. The code uses classes from the ObjectWeb ASM BCEL which must be present in the JVM classpath. Exactly which version of the ASM BCEL library is needed, and whether it works with the current ABCL is untested. ABCL issue #153 tracks the work necessary to support this in the contemporary ABCL implementation.

But if one has an existing Java interface for which one would like to use Lisp based methods to provide an implementation, the process is considerably simpler (and supported!)

The relevant function is JAVA:JINTERFACE-IMPLEMENTATION whose use is demonstrated in the BankAccount example.

For the Java interface defined as

public interface BankAccount {
  public int getBalance();
  public void deposit(int amount);
  public void withdraw(int amount); 
}

The following Lisp code creates a usable Java Proxy in the current JVM:

 (defparameter *bank-account-impl*
  (let ((balance 1000))
    (jinterface-implementation
     "BankAccount"

     "getBalance" 
       (lambda ()
         balance)
     "deposit" 
       (lambda (amount) 
         (let ((amount (jobject-lisp-value amount)))
           (setf balance (+ balance amount))))  
     "withdraw" 
       (lambda (amount)
         (let ((amount (jobject-lisp-value amount)))
           (setf balance (- balance amount)))))))

To get a reference to this implementation from Java, one uses the code in BankMainAccount.java

  ...
  org.armedbear.lisp.Package defaultPackage
    = Packages.findPackage("CL-USER");
  Symbol bankAccountImplSymbol
    = defaultPackage.findAccessibleSymbol("*BANK-ACCOUNT-IMPL*");
  LispObject value = bankAccountImplSymbol.symbolValue();
  Object object =  ((JavaObject) value).getObject();
  BankAccount account = (BankAccount) object;
  System.out.println("Initial balance: " + account.getBalance());
  account.withdraw(500);
  System.out.println("After withdrawing 500: " + account.getBalance());
  ... 
like image 94
easyE Avatar answered Nov 01 '22 07:11

easyE