Crate imageflow [−] [src]
Purpose
This module contains the functions exported for use by other languages.
If you're writing bindings, you're in the right place. Don't use imageflow_core::ffi, that's not correct - those are unstable and will disappear as C is replaced with Rust.
Don't call functions against the same context from multiple threads. You can create contexts from as many threads as you like, but you are responsible for synchronizing API calls on a per-context basis if you want to use one context from multiple threads. No use case for multithreaded Context access has been presented, so it is out of scope for API design.
Memory Lifetimes
In order to prevent dangling pointers, we must be correct about memory lifetimes.
... when allocated by Imageflow, assume the lifetime of the context
In Imageflow, by default, all things created with a context will be destroyed when the context is destroyed. Don't try to access ANYTHING imageflow has provided after the context is gone.
This is very nice, as it means that a client's failure to clean up
will have limited impact on the process as a whole - as long as the client at minimum
calls flow_context_destroy
at the end of all possible code paths.
However, waiting to free memory and run destructors until the context is destroyed is not ideal; it increases our peak memory usage/needs and may cause operations to fail that would otherwise succeed.
There are two ways to mitigate this.
- When creating an I/O object, request it be cleaned up when the first job it is assigned to is cleaned up (instead of the context).
- Manually invoke the corresponding destroy function when you're done with the thing.
Destroying things
- An
imageflow_context
should ALWAYS be destroyed withimageflow_context_destroy
- JsonResponse structures should be released with
imageflow_json_response_destroy
- An
imageflow_job
can be destroyed early withimageflow_job_destroy
... when allocated by the client, Imageflow only borrows it for the invocation
Imageflow assumes that, at minimum, all pointers that you provide to it will, at minimum, remain valid for the duration of the API call. We'll call this 'borrowing'. Imageflow is just borrowing it for a bit; not taking ownership of the thing.
This may seem obvious, but it is not, in fact, guaranteed by garbage-collected languages. They are often oblivious to pointers, and cannot track what data is and is not referenced. Therefore, we suggest that you ensure every allocation made (and handed to Imageflow) is referenced after the imageflow API call, preferably in a way that will not be optimized away at runtime. Many languages and FFI libraries offer a utility method just for this purpose.
... although Imageflow may borrow some strings for the life of the context, yet not own them.
This happens for strings that are usually static constants, and unlikely to be allocated on the heap anyway.
- When an Imageflow API asks for a filename, function name, or error message, it will
assume that those strings are pointers that (a) Imageflow is not
responsible for freeing, and (b) will (at least) outlive the
context
.
... and it should be very clear when Imageflow is taking ownership of something you created!
When Imageflow needs continued access to data that is NOT highly likely to be static, it will be documented.
- If you give Imageflow a buffer to read an image from, it will need to access that buffer much longer than the initial io_create call.
What if I need something to outlive the context
?
Copy it before the context is destroyed.
Data types
Reference for those creating bindings in other languages
Two types are platform-specific - use the corresponding pointer or size type that varies with your platform.
- libc::c_void (or anything *mut or *const): Platform-sized pointer. 32 or 64 bits.
- The above includes *mut Context, *mut Job, *mut JobIo, etc.
- libc::size_t (or usize): Unsigned integer, platform-sized. 32 or 64 bits.
Treat *mut Context, *mut Job, *mut JobIo, *mut JsonResponse ALL as opaque pointers.
Strings
ASCII is a safe subset of UTF-8; therefore wherever Imageflow asks for UTF-8 encoded bytes, you may provide ASCII instead.
You will provide Imageflow with strings in one of 3 ways:
* UTF-8 null-terminated. You'll see something like libc::char
, but no length parameter. Short and likely static strings are usually transmitted this way.
* Operating system null-terminated. Only applicable to imageflow_io_create_for_file
.
* UTF-8 buffer with length. You'll usually see *const u8 and a length parameter. This is common for buffers of UTF-8 encoded json.
filename: *const libc::c_char function_name: *const libc::c_char
Fixed size
- u8 (1 unsigned byte)
- bool (C99 style, 1 byte, value 0 or 1)
- The rest seem self-explanatory.
i
prefixes signed intsu
prefixes unsigned ints.f
prefixes floating point
Structs
Consider all structures to be opaque. Do not attempt to access fields by offsets; rather, use the accessor functions provided.
Failure behavior
If you provide a null pointer for imageflow_context
, then the process should terminate.
This "fail fast" behavior offers the best opportunity for a useful stacktrace, and it's not a
recoverable error.
Macros
static_char |
Creates a static, null-terminated Rust string, and
returns a |
Structs
Context | |
Job | |
JobIo | |
JsonResponse |
|
Enums
CleanupWith |
When a resource should be closed/freed/cleaned up |
Direction |
Input or output? |
IoMode |
What is possible with the IO object |
Lifetime |
How long the provided pointer/buffer will remain valid. Callers must prevent the memory from being freed or moved until this contract expires. |
Functions
exercise_create_destroy | |
exercise_error_handling | |
exercise_json_message | |
imageflow_context_add_to_callstack⚠ |
Adds the given filename, line number, and function name to the call stack.
Strings |
imageflow_context_begin_terminate⚠ |
Begins the process of destroying the context, yet leaves error information intact so that any errors in the tear-down process can be debugged with imageflow_context_error_and_stacktrace. |
imageflow_context_clear_error⚠ |
Clear the error state. This assumes that you know which API call failed and the problem has been resolved. Don't use this unless you're sure you've accounted for all possible inconsistent state (and fully understand the code paths that led to the error). |
imageflow_context_create⚠ |
Creates and returns an imageflow context. An imageflow context is required for all other imageflow API calls. |
imageflow_context_destroy⚠ |
Destroys the imageflow context and frees the context object. Only use this with contexts created using imageflow_context_create |
imageflow_context_error_and_stacktrace⚠ |
Prints the error messages and stacktrace to the given buffer in UTF-8 form; writes a null character to terminate the string, and ALSO returns the number of bytes written. |
imageflow_context_error_code⚠ |
Returns the numeric code associated with the error. |
imageflow_context_has_error⚠ |
Returns true if the context is in an error state. You must immediately deal with the error, as subsequent API calls will fail or cause undefined behavior until the error state is cleared |
imageflow_context_memory_allocate⚠ |
Allocates zeroed memory that will be freed with the context. |
imageflow_context_memory_free⚠ |
Frees memory allocated with imageflow_context_memory_allocate early. |
imageflow_context_print_and_exit_if_error⚠ |
Prints the error to stderr and exits the process if an error has been raised on the context. If no error is present, the function returns false. |
imageflow_context_raise_error⚠ |
Raises an error on the context. |
imageflow_context_send_json⚠ |
Sends a JSON message to the imageflow_context |
imageflow_io_create_for_file⚠ |
Creates an imageflow_io object to wrap a filename. |
imageflow_io_create_for_output_buffer⚠ |
Creates an imageflow_io structure for writing to an expanding memory buffer. |
imageflow_io_create_from_buffer⚠ |
Creates an imageflow_io structure for reading from the provided buffer. You are ALWAYS responsible for freeing the memory provided in accordance with the Lifetime value. If you specify OutlivesFunctionCall, then the buffer will be copied. |
imageflow_io_get_output_buffer⚠ |
Provides access to the underlying buffer for the given imageflow_io object. |
imageflow_job_add_io⚠ |
Associates the imageflow_io object with the job and the assigned io_id. |
imageflow_job_create⚠ |
Creates an imageflow_job, which permits the association of imageflow_io instances with numeric identifiers and provides a 'sub-context' for job execution |
imageflow_job_destroy⚠ |
Destroys the provided imageflow_job |
imageflow_job_get_io⚠ |
Looks up the imageflow_io pointer from the provided io_id |
imageflow_job_get_output_buffer_by_id⚠ |
Provides access to the underlying buffer for the given imageflow_io object. |
imageflow_job_send_json⚠ |
Sends a JSON message to the imageflow_job |
imageflow_json_response_destroy⚠ |
Frees memory associated with the given object (and owned objects) after running any owned or attached destructors. Returns false if something went wrong during tear-down. |
imageflow_json_response_read⚠ |
Writes fields from the given imageflow_json_response to the locations referenced. The buffer pointer sent out will be a UTF-8 byte array of the given length (not null-terminated). It will also become invalid if the JsonResponse associated is freed, or if the context is destroyed. |