aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChouser <chouser@n01se.net>2008-08-07 21:11:50 +0000
committerChouser <chouser@n01se.net>2008-08-07 21:11:50 +0000
commit809e9570ed4fbcfa077fe41a7432803de08ecb0c (patch)
treec32b095168e8c68338c7c7f555ec012f39d90184
parentae151e2bab2eae7c4af643f7d5128f5457bfbead (diff)
Rename functions and merge normally desired behavior into the gen-interface function. Also add some docs.
-rw-r--r--gen_interface/gen_interface.clj51
1 files changed, 43 insertions, 8 deletions
diff --git a/gen_interface/gen_interface.clj b/gen_interface/gen_interface.clj
index 10b8ea06..fc66fc16 100644
--- a/gen_interface/gen_interface.clj
+++ b/gen_interface/gen_interface.clj
@@ -16,7 +16,11 @@
'(clojure.asm.commons Method GeneratorAdapter)
'(java.io File))
-(defn gen-interface
+(defn gen-and-return-interface
+ "Uses the given specs to generate a Java interface. Returns a map
+ with :iname being the Java internal name of the interface, and
+ :bytecode being an array of Bytes of the Java bytecode. You'll
+ almost always want to use gen-interface instead."
[cname extends & methods]
(let [to-iname (fn [c] (if (instance? Class c)
(.. Type (getType c) getInternalName)
@@ -41,13 +45,22 @@
{:iname iname :bytecode (.toByteArray cv)}))
(defn gen-and-load-interface
+ "Uses the given specs to generate and immediately load a Java
+ interface. This is not generally useful since you'll usually want
+ a .class file in order to write Java code that uses the generated
+ interface. See gen-interface instead."
[cname & args]
- (let [{:keys [iname bytecode]} (apply gen-interface cname args)]
+ (let [{:keys [iname bytecode]} (apply gen-and-return-interface cname args)]
(.. clojure.lang.RT ROOT_CLASSLOADER (defineClass (str cname) bytecode))))
(defn gen-and-save-interface
+ "Uses the given specs to generate a Java interface and save it to a
+ .class file. Returns the bytecode of the interface. If you intend
+ to use this interface immediately (for example to refer to it in a
+ later gen-interface call as a parameter type, return type, or super
+ class), you'll want to use gen-interface instead."
[path cname & args]
- (let [{:keys [iname bytecode]} (apply gen-interface cname args)
+ (let [{:keys [iname bytecode]} (apply gen-and-return-interface cname args)
file (File. path (str (.replace (str cname) \. File/separatorChar)
".class"))]
(try
@@ -55,15 +68,37 @@
(catch java.io.IOException e
(throw (Exception. (str "Failed to create " file) e))))
(with-open f (java.io.FileOutputStream. file)
- (.write f bytecode))))
+ (.write f bytecode))
+ bytecode))
+(defn gen-interface
+ "Uses the given specs to generate a Java interface, save it to a
+ .class file, and immediately load it so it's ready for use by
+ subsequent gen-interface calls. The path is the base classpath
+ under which the .class file will be written. cname is the
+ fully-qualified classname (string or symbol) of the interface to be
+ created (note that the appropriate sub-directories under path must
+ already exist or this will throw an exception). The next arg must
+ be a collection of classes this interface will extend (each may be
+ a string, symbol, or a class). This may be followed by any number
+ of: methodName, arg types, return type."
+ [path cname & args]
+ (.. clojure.lang.RT ROOT_CLASSLOADER
+ (defineClass (str cname) (apply gen-and-save-interface path cname args))))
(comment
-(gen-and-load-interface 'net.n01se.Foo [Appendable]
- 'foo [] Integer
- 'bar [Integer String] Double)
-(gen-and-save-interface "/tmp" 'net.n01se.Bar ['net.n01se.Other Iterable])
+(gen-interface "/tmp" 'net.n01se.Foo [Appendable]
+ 'foo [] Integer
+ 'bar [Integer String] Double)
+
+; save is used in this example because I want to refer to a class
+; that's not yet defined in this runtime (Other). It's possible by
+; not loading the interface and specifying the class via a quoted
+; symbol, but this isn't really recommended. Why not make sure Other
+; is defined and then just use gen-interface?
+(gen-and-save-interface "/tmp" 'net.n01se.Bar ['net.n01se.Other Iterable]
+ 'baz [] net.n01se.Foo)
(prn :isInterface (.isInterface (identity net.n01se.Foo)))
(prn :interfaces (seq (.getGenericInterfaces (identity net.n01se.Foo))))