Merge branch 'release/2021-10-06'

This commit is contained in:
Joshua Suskalo 2021-10-06 11:39:29 -05:00
commit 51c62decca
4 changed files with 41 additions and 13 deletions

View file

@ -1,6 +1,19 @@
# Change Log # Change Log
All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).
## [0.1.205]
### Added
- An `address?` predicate
### Fixed
- Compound types caused problems in arglists meta on expansion of `defcfn`
- Compound types were not allowed as return types in `defcfn`
- `nil` was not considered a null pointer
- Primitive-serializing types fail to compile as arguments to downcall handles
- Primitive-serializing types fail to load as arguments to upcall functions
- Void return types on upcalls crash the JVM
- Invalid implementation of serialize-into for primitive types
## [0.1.192] - 2021-09-30 ## [0.1.192] - 2021-09-30
### Added ### Added
- An `::ffi/address` key to wrapper functions' metadata - An `::ffi/address` key to wrapper functions' metadata
@ -28,6 +41,7 @@ All notable changes to this project will be documented in this file. This change
- Support for serializing and deserializing arbitrary Clojure functions - Support for serializing and deserializing arbitrary Clojure functions
- Support for serializing and deserializing arbitrary Clojure data structures - Support for serializing and deserializing arbitrary Clojure data structures
[0.1.205]: https://github.com/IGJoshua/coffi/compare/v0.1.192...v0.1.205
[0.1.192]: https://github.com/IGJoshua/coffi/compare/v0.1.184...v0.1.192 [0.1.192]: https://github.com/IGJoshua/coffi/compare/v0.1.184...v0.1.192
[0.1.184]: https://github.com/IGJoshua/coffi/compare/v0.1.176...v0.1.184 [0.1.184]: https://github.com/IGJoshua/coffi/compare/v0.1.176...v0.1.184
[0.1.176]: https://github.com/IGJoshua/coffi/compare/v0.1.169...v0.1.176 [0.1.176]: https://github.com/IGJoshua/coffi/compare/v0.1.169...v0.1.176

View file

@ -17,8 +17,8 @@ This library is available on Clojars. Add one of the following entries to the
`:deps` key of your `deps.edn`: `:deps` key of your `deps.edn`:
```clojure ```clojure
org.suskalo/coffi {:mvn/version "0.1.192"} org.suskalo/coffi {:mvn/version "0.1.205"}
io.github.IGJoshua/coffi {:git/tag "v0.1.192" :git/sha "9d65f47"} io.github.IGJoshua/coffi {:git/tag "v0.1.205" :git/sha "0149012"}
``` ```
If you use this library as a git dependency, you will need to prepare the If you use this library as a git dependency, you will need to prepare the

View file

@ -108,9 +108,10 @@
(defn- insn-layout (defn- insn-layout
"Gets the type keyword or class for referring to the type in bytecode." "Gets the type keyword or class for referring to the type in bytecode."
[type] [type]
(if (some-> (mem/primitive-type type) (not= ::mem/pointer)) (when-some [prim (mem/primitive-type type)]
(keyword (name type)) (if (not= prim ::mem/pointer)
(mem/java-layout type))) (keyword (name prim))
(mem/java-layout type))))
(def ^:private unbox-fn-for-type (def ^:private unbox-fn-for-type
"Map from type name to the name of its unboxing function." "Map from type name to the name of its unboxing function."
@ -320,7 +321,7 @@
[:getfield :this "upcall_ifn" IFn] [:getfield :this "upcall_ifn" IFn]
(map-indexed (map-indexed
(fn [idx arg] (fn [idx arg]
[[(load-instructions arg :aload) (inc idx)] [[(load-instructions (mem/primitive-type arg) :aload) (inc idx)]
(to-object-asm arg)]) (to-object-asm arg)])
arg-types) arg-types)
[:invokeinterface IFn "invoke" (repeat (inc (count arg-types)) Object)] [:invokeinterface IFn "invoke" (repeat (inc (count arg-types)) Object)]
@ -503,7 +504,7 @@
(s/or :string string? (s/or :string string?
:symbol simple-symbol?)) :symbol simple-symbol?))
:native-arglist (s/coll-of ::mem/type :kind vector?) :native-arglist (s/coll-of ::mem/type :kind vector?)
:return-type qualified-keyword? :return-type ::mem/type
:wrapper (s/? :wrapper (s/?
(s/cat (s/cat
:native-fn simple-symbol? :native-fn simple-symbol?
@ -581,7 +582,11 @@
(or old-list (or old-list
(seq arglists) (seq arglists)
(list (list
(mapv (comp symbol name) (mapv (fn [type]
(-> (cond-> type
(vector? type) first)
name
symbol))
(:native-arglist args))))))) (:native-arglist args)))))))
(assoc (:attr-map args) (assoc (:attr-map args)
::address address))) ::address address)))

View file

@ -128,7 +128,14 @@
(defn null? (defn null?
"Checks if a memory address is null." "Checks if a memory address is null."
[addr] [addr]
(.equals (MemoryAddress/NULL) addr)) (or (.equals (MemoryAddress/NULL) addr) (not addr)))
(defn address?
"Checks if an object is a memory address.
`nil` is considered an address."
[addr]
(or (nil? addr) (instance? MemoryAddress addr)))
(defn slice-global (defn slice-global
"Gets a slice of the global address space. "Gets a slice of the global address space.
@ -315,20 +322,22 @@
(defmethod serialize* :default (defmethod serialize* :default
[obj type _scope] [obj type _scope]
(if-let [prim (primitive-type type)] (if-let [prim (primitive-type type)]
((primitive-cast prim) obj) (when-not (= ::void prim)
((primitive-cast prim) obj))
(throw (ex-info "Attempted to serialize a non-primitive type with primitive methods" (throw (ex-info "Attempted to serialize a non-primitive type with primitive methods"
{:type type {:type type
:object obj})))) :object obj}))))
(defmethod serialize* ::pointer (defmethod serialize* ::pointer
[obj type scope] [obj type scope]
(when-not (null? obj) (if-not (null? obj)
(if (sequential? type) (if (sequential? type)
(with-acquired [scope] (with-acquired [scope]
(let [segment (alloc-instance (second type) scope)] (let [segment (alloc-instance (second type) scope)]
(serialize-into obj (second type) segment scope) (serialize-into obj (second type) segment scope)
(address-of segment))) (address-of segment)))
obj))) obj)
(MemoryAddress/NULL)))
(defmulti serialize-into (defmulti serialize-into
"Writes a serialized version of the `obj` to the given `segment`. "Writes a serialized version of the `obj` to the given `segment`.
@ -352,7 +361,7 @@
(defmethod serialize-into :default (defmethod serialize-into :default
[obj type segment scope] [obj type segment scope]
(if-some [prim-layout (primitive-type type)] (if-some [prim-layout (primitive-type type)]
(with-acquired [(segment-scope scope) scope] (with-acquired [(segment-scope segment) scope]
(serialize-into (serialize* obj type scope) prim-layout segment scope)) (serialize-into (serialize* obj type scope) prim-layout segment scope))
(throw (ex-info "Attempted to serialize an object to a type that has not been overriden" (throw (ex-info "Attempted to serialize an object to a type that has not been overriden"
{:type type {:type type