ClojureCPP is a Clojure library for integrating C/C++ based libraries available through JavaCPP. It is much more than a wrapper around JavaCPP that hides Java interop. It enables you to use JavaCPP's Pointer-based infrastucture the Clojure way; exposing what is absolutely necessary, automating whatever boilerplate that can be automated under the hood, and protecting yourself from shooting yourself in the foot with memory leaks and segmentation faults as much as possible (95%? 89%? who knows, but not 100%). You still have to be careful, because you're stepping outside the JVM, but you'll write a lot less code, your code will fit nicely with the rest of Clojure code in your program, and you will do the wrong thing less often.
The center piece of this library is JavaCPP's Pointer
class. Almost all JavaCPP interop methods
accept subclasses of Pointer
as arguments (along with good old Java primitives such as int
or double
).
Very often, these pointers are pointers to off-heap primitive memory blocks that are not managed by
your JVM, which are managed by classes such as DoublePointer
or FloatPointer
. That is because
many C libraries use the respective arrays. Some libraries define their own structs; these are
typically represented as specialized Pointer
sublasses by JavaCPP. Typical examples would be
CUDA or MKL wrappers. You can explore ClojureCUDA and Neanderthal code for real-world examples
of how to deal with these if you need to create a new wrapper for a new library. Fortunately,
if someone else has already done the integration, you might even write code without thinking
much outside of Clojure. Depending of your grasp of the basics of C and/or C++, it still might be
a good idea to read some introduction to JavaCPP.
Note that ClojureCPP is well integrated into Clojure and Uncomplicate family of libraries,
which means that lots of functionality is integrated into general functions such as
release
, size
, bytesize
, sizeof
from uncomplicate.commons
, or fmap
, fmap!
,
fold
, op
from uncomplicate.fluokitten
, or similar polymorphic functions. Ideally,
you'll prefer these over fiddling with lower-level ClojureCPP-specific code (when possible).
Here's a loose grouping of ClojureCPP functions:
System functions give you some insight int o the overall system, memory, and allocations:
physical-bytes
, available-physical-bytes
, max-physical-bytes
, total-physical-bytes
,
tracked-bytes
, max-tracked-bytes
and pointers-count
.
Constructors. The pointers that you'll use throughout your code are explicitly created by these
constructors. Alternatively, you'll work with pointers returned by custom functions from many of
C libraries available through JavaCPP (such as CUDA etc.). You'll use these functions a lot.
pointer
, [[pointer-pointer]], [[byte-pointer]], [[keyword-pointer]], [[string-pointer]],
[[bool-pointer]], [[bool-pointer]], [[clong-pointer]], [[size-t-pointer]], [[char-pointer]],
[[short-pointer]], [[int-pointer]], [[long-pointer]], [[float-pointer]], [[double-pointer]],
and [[function-pointer]].
Memory allocation functions with standard C counterparts (you typically don't have to use these
unless you're writing low-level stuff):
malloc!
, calloc!
, realloc!
, free!
, memcmp
, memcpy!
, memmove!
,
memset!
, and zero!
.
General pointer features:
pointer-type
, pointer-class
, and type-pointer
are convenience mappings between
keywords representing primitive types, built-in pointer classes, and pointer constructor functions,
so you can, for example, use :float
or Float
instead if importing FloatPointer
. That also helps in
integration with other systems without coupling with JavaCPP types.
The following functions give you an insight into the properties of the pointer at hand. Most of
the time, these properties are set by other functions to their right values, but sometimes you
want to see details or even set something yourself (but be careful of papercuts!).
address
, null?
, capacity
, capacity!
, limit
, limit!
, position
, position!
,
This group of functions do some pointer arithmetic, type casts, or type conversions:
get-pointer
, safe
, safe2
, ptr*
, ptr
, ptr2
,
float-ptr*
, float-ptr
, float-ptr2
, double-ptr*
, double-ptr
, double-ptr2
,
long-ptr*
, long-ptr
, long-ptr2
, int-ptr*
, int-ptr
, int-ptr2
,
short-ptr*
, short-ptr
, short-ptr2
, short-ptr*
, short-ptr
, short-ptr2
,
byte-ptr*
, byte-ptr
, byte-ptr2
, size-t-ptr*
, size-t-ptr
, size-t-ptr2
,
clong-ptr*
, clong-ptr
, clong-ptr2
, bool-ptr*
, bool-ptr
, bool-ptr2
,
char-ptr*
, char-ptr
, and char-ptr2
.
Java and Clojure conversions to Java buffers or Clojure vectors and sequences:
as-byte-buffer
, as-buffer
, [[pointer-vec]], pointer-seq
,
Polymorphic access to data in memory blocks managed by a pointer: [[get!]], [[put!]], [[get-entry!]], [[put-entry!]], and [[fill!]]
Raw access to bytes from a BytePointer
:
get-keyword
, put-keyword!
, get-string
, put-string!
,
get-pointer-value
, [[put-pointer-value]], get-unsigned
, put-unsigned!
, get-bool
,
put-bool!
, get-char
, put-char!
, get-int
, put-int!
, get-short
, put-short!
,
get-long
, put-long!
, get-byte
, put-byte!
, get-short
, put-short!
,
get-double
, put-double!
, get-float
, put-float!
, and get-string-bytes
.
Please read JavaCPP javadoc for more internal details when necessary. Also, getting familiar with common C library functions can be very helpful.
Please check out uncomplicate.clojure-cpp-test
for examples of how to use these functions!
ClojureCPP is a Clojure library for integrating C/C++ based libraries available through JavaCPP. It is much more than a wrapper around JavaCPP that hides Java interop. It enables you to use JavaCPP's Pointer-based infrastucture the Clojure way; exposing what is absolutely necessary, automating whatever boilerplate that can be automated under the hood, and protecting yourself from shooting yourself in the foot with memory leaks and segmentation faults as much as possible (95%? 89%? who knows, but not 100%). You still have to be careful, because you're stepping outside the JVM, but you'll write a lot less code, your code will fit nicely with the rest of Clojure code in your program, and you will do the wrong thing less often. The center piece of this library is JavaCPP's `Pointer` class. Almost all JavaCPP interop methods accept subclasses of `Pointer` as arguments (along with good old Java primitives such as `int` or `double`). Very often, these pointers are pointers to off-heap primitive memory blocks that are not managed by your JVM, which are managed by classes such as `DoublePointer` or `FloatPointer`. That is because many C libraries use the respective arrays. Some libraries define their own structs; these are typically represented as specialized `Pointer` sublasses by JavaCPP. Typical examples would be CUDA or MKL wrappers. You can explore ClojureCUDA and Neanderthal code for real-world examples of how to deal with these if you need to create a new wrapper for a new library. Fortunately, if someone else has already done the integration, you might even write code without thinking much outside of Clojure. Depending of your grasp of the basics of C and/or C++, it still might be a good idea to read some [introduction to JavaCPP](https://github.com/bytedeco/javacpp). Note that ClojureCPP is well integrated into Clojure and Uncomplicate family of libraries, which means that lots of functionality is integrated into general functions such as `release`, `size`, `bytesize`, `sizeof` from `uncomplicate.commons`, or `fmap`, `fmap!`, `fold`, `op` from `uncomplicate.fluokitten`, or similar polymorphic functions. Ideally, you'll prefer these over fiddling with lower-level ClojureCPP-specific code (when possible). Here's a loose grouping of ClojureCPP functions: - System functions give you some insight int o the overall system, memory, and allocations: [[physical-bytes]], [[available-physical-bytes]], [[max-physical-bytes]], [[total-physical-bytes]], [[tracked-bytes]], [[max-tracked-bytes]] and [[pointers-count]]. - Constructors. The pointers that you'll use throughout your code are explicitly created by these constructors. Alternatively, you'll work with pointers returned by custom functions from many of C libraries available through JavaCPP (such as CUDA etc.). You'll use these functions a lot. [[pointer]], [[pointer-pointer]], [[byte-pointer]], [[keyword-pointer]], [[string-pointer]], [[bool-pointer]], [[bool-pointer]], [[clong-pointer]], [[size-t-pointer]], [[char-pointer]], [[short-pointer]], [[int-pointer]], [[long-pointer]], [[float-pointer]], [[double-pointer]], and [[function-pointer]]. - Memory allocation functions with standard C counterparts (you typically don't have to use these unless you're writing low-level stuff): [[malloc!]], [[calloc!]], [[realloc!]], [[free!]], [[memcmp]], [[memcpy!]], [[memmove!]], [[memset!]], and [[zero!]]. - General pointer features: [[pointer-type]], [[pointer-class]], and [[type-pointer]] are convenience mappings between keywords representing primitive types, built-in pointer classes, and pointer constructor functions, so you can, for example, use `:float` or `Float` instead if importing `FloatPointer`. That also helps in integration with other systems without coupling with JavaCPP types. The following functions give you an insight into the properties of the pointer at hand. Most of the time, these properties are set by other functions to their right values, but sometimes you want to see details or even set something yourself (but be careful of papercuts!). [[address]], [[null?]], [[capacity]], [[capacity!]], [[limit]], [[limit!]], [[position]], [[position!]], - This group of functions do some pointer arithmetic, type casts, or type conversions: [[get-pointer]], [[safe]], [[safe2]], [[ptr*]], [[ptr]], [[ptr2]], [[float-ptr*]], [[float-ptr]], [[float-ptr2]], [[double-ptr*]], [[double-ptr]], [[double-ptr2]], [[long-ptr*]], [[long-ptr]], [[long-ptr2]], [[int-ptr*]], [[int-ptr]], [[int-ptr2]], [[short-ptr*]], [[short-ptr]], [[short-ptr2]], [[short-ptr*]], [[short-ptr]], [[short-ptr2]], [[byte-ptr*]], [[byte-ptr]], [[byte-ptr2]], [[size-t-ptr*]], [[size-t-ptr]], [[size-t-ptr2]], [[clong-ptr*]], [[clong-ptr]], [[clong-ptr2]], [[bool-ptr*]], [[bool-ptr]], [[bool-ptr2]], [[char-ptr*]], [[char-ptr]], and [[char-ptr2]]. - Java and Clojure conversions to Java buffers or Clojure vectors and sequences: [[as-byte-buffer]], [[as-buffer]], [[pointer-vec]], [[pointer-seq]], - Polymorphic access to data in memory blocks managed by a pointer: [[get!]], [[put!]], [[get-entry!]], [[put-entry!]], and [[fill!]] - Raw access to bytes from a `BytePointer`: [[get-keyword]], [[put-keyword!]], [[get-string]], [[put-string!]], [[get-pointer-value]], [[put-pointer-value]], [[get-unsigned]], [[put-unsigned!]], [[get-bool]], [[put-bool!]], [[get-char]], [[put-char!]], [[get-int]], [[put-int!]], [[get-short]], [[put-short!]], [[get-long]], [[put-long!]], [[get-byte]], [[put-byte!]], [[get-short]], [[put-short!]], [[get-double]], [[put-double!]], [[get-float]], [[put-float!]], and [[get-string-bytes]]. Please read [JavaCPP javadoc](http://bytedeco.org/javacpp/apidocs/overview-summary.html) for more internal details when necessary. Also, getting familiar with common C library functions can be very helpful. Please check out `uncomplicate.clojure-cpp-test` for examples of how to use these functions!
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close