Dynamically Creating Java Interfaces
As of r13078, one can use the classwriter in the JVM package to dynamically create a Java interface.
An example of work in progress to use dynamically created Java interfaces for callbacks in JNA with CFFI:
(jvm::define-class-name +callback-object+ "com.sun.jna.Callback")
(defconstant +dynamic-callback-package+ "org/armedbear/jna/dynamic/callbacks")
#|
TEST: (define-jinterface :int '(foo) '(:int))
|#
(defun define-interface (rettype arg-names arg-types)
"Returns the Java byte[] array of a class representing a Java interface."
(declare (ignore rettype arg-names arg-types)) ;; XXX unimplemented
(let* ((class-name-string (format nil "~A/~A"
+dynamic-callback-package+ (symbol-name (gensym))))
(class-name (jvm::make-jvm-class-name class-name-string))
(class (jvm::make-class-interface-file class-name))
(method (jvm::make-jvm-method "callback" :int '(:int)
:flags '(:public :abstract))))
(jvm::class-add-superinterface class +callback-object+)
(jvm::class-add-method class method)
(jvm::finalize-class-file class)
(let ((s (sys::%make-byte-array-output-stream)))
(jvm::write-class-file class s)
(sys::%get-output-stream-bytes s))))
(defun load-class (class-bytes)
"Load the Java byte[] array CLASS-BYTES as a Java class."
(let ((load-class-method
(jmethod "org.armedbear.lisp.JavaClassLoader"
"loadClassFromByteArray" "[B")))
(jcall load-class-method java::*classloader* class-bytes)))
(defun write-class (class-bytes pathname)
"Write the Java byte[] array CLASS-BYTES to PATHNAME."
(with-open-file (stream pathname
:direction :output
:element-type '(signed-byte 8))
(dotimes (i (jarray-length class-bytes))
(write-byte (jarray-ref class-bytes i) stream))))
Last modified 15 years ago
Last modified on 12/01/10 22:48:51