This module provides functions which offer a low-level interface for the purpose of marshalling data between Mars and foreign (native) code. These functions provide conversions between the regular Num and foreign CInt types, as well as pointer allocation, manipulation, and dereferencing.
Warning
Mars is, fundamentally, a pure language. This means that no function can modify an existing value or global state, only return a value (and perform input/output, which while technically impure, isn’t considered “impure” in Mars).
The functions in this module break that purity by providing direct access to memory via pointers. They can also be used to crash the program or violate type constraints. They should not be considered part of the language semantics, and are not intended to be used by most code. They are provided to allow compatibility with code written in other languages. Use at your own risk.
These functions convert back and forth between Num and each of the native types. The conversions from Num raise an error if the value is out of range of the target type. The integral types have separate signed and unsigned conversion functions.
Converts a Num to a signed CChar. It is an error if value is not an integer in the range [-128, 127].
Converts a Num to an unsigned CChar. It is an error if value is not an integer in the range [0, 255].
Converts a Num to a signed CShort. It is an error if value is not an integer in the range [-32768, 32767].
Converts a Num to an unsigned CShort. It is an error if value is not an integer in the range [0, 65535].
Converts a Num to a signed CInt. It is an error if value is not an integer that can be represented in sizeof_cint bytes.
Converts a signed CInt to a Num.
Warning
If the value’s magnitude is greater than 2^53, this may result in rounding errors. (This is only a possibility if sizeof_cint >= 7.)
Converts a Num to an unsigned CInt. It is an error if value is not a positive integer that can be represented in sizeof_cint bytes.
Converts an unsigned CInt to a Num.
Warning
If the value’s magnitude is greater than 2^53, this may result in rounding errors. (This is only a possibility if sizeof_cint >= 7.)
Warning
This may result in rounding errors. Furthermore, values too large to be represented in a single-precision float will be rounded to negative or positive infinity.
Converts a Num to a CPtr. It is an error if value is not a positive integer that can be represented in sizeof_cptr bytes.
Warning
On a 64-bit system, this may result in rounding errors. Therefore, this function should generally be avoided. Never attempt to pass the result of this function back to num_cptr, because the rounding error may alter the pointer’s address. Pointer arithmetic should be performed using cptr_add and cptr_diff instead.
These constants get the size, in bytes, of each native type. This is equivalent to the sizeof operator in C. These should be used with malloc to determine how much memory to allocate for a native value or an array of them. These should also be used with cptr_add when indexing into an array.
The number of bytes of memory used by a CChar. This is always 1. This is equivalent to the C expression sizeof(char).
The number of bytes of memory used by a CChar. This is 2 on all supported platforms. This is equivalent to the C expression sizeof(short).
The number of bytes of memory used by a CInt. This is typically 4, on both 32-bit and 64-bit machines. This is equivalent to the C expression sizeof(int).
The number of bytes of memory used by a CFloat. This is 4 on all supported platforms. This is equivalent to the C expression sizeof(float).
These functions directly manipulate pointers, without having to convert back and forth to Num.
Adds offset bytes to pointer and returns the result. The offset may be a negative number. It is an error if offset is not a whole number. If the result is less than 0 or larger than the maximum pointer value, behaviour is undefined (typically wraps).
This is the preferred way to perform pointer arithmetic, such as when indexing into arrays. This is equivalent to the C expression (char*) pointer + offset.
Note
This is different from pointer arithmetic in C, which offsets the pointer by offset multiplied by the size of the pointed-to type. In order to index into a native array in Mars, the index must be manually multiplied by the size of the type. For example, if p points to an array of floats, element i is addressed as cptr_add(p, i * sizeof_cfloat).
Subtracts the pointer y from the pointer x, returning the difference between them in bytes. This is equivalent to the C expression (char*) x - (char*) y.
Warning
On a 64-bit system, this may result in rounding errors if x and y are sufficiently far apart. Therefore, this function should only be used when x and y are known to be pointers to the same contiguously allocated block.
As with the malloc function in the C standard library, allocates size bytes of memory and returns a pointer to that memory. The memory will be uninitialised.
A runtime error is triggered if the program is out of memory when malloc is called; this function never returns nullptr.
Memory allocated by malloc cannot be used by regular Mars code, but it can be manipulated by other functions in the native module, as well as being passed to functions written in other languages (which is why it is provided).
There is no corresponding free function. As Mars currently uses the Boehm garbage collector, memory allocated with malloc should automatically be freed when it is no longer in use.
These functions read or write values pointed to by a pointer. There is a separate pair of functions for dereferencing pointers to each native type. In all of these functions, behaviour is undefined if pointer is not a valid memory address.
Read a CChar value from the memory location pointer. This is equivalent to the C expression *((char*) pointer).
Write a CChar value to the memory location pointer. This is equivalent to the C expression *((char*) pointer) = value, pointer.
Read a CShort value from the memory location pointer. This is equivalent to the C expression *((short*) pointer).
Write a CShort value to the memory location pointer. This is equivalent to the C expression *((short*) pointer) = value, pointer.
Read a CInt value from the memory location pointer. This is equivalent to the C expression *((int*) pointer).
Write a CInt value to the memory location pointer. This is equivalent to the C expression *((int*) pointer) = value, pointer.
Read a CFloat value from the memory location pointer. This is equivalent to the C expression *((float*) pointer).
Write a CFloat value to the memory location pointer. This is equivalent to the C expression *((float*) pointer) = value, pointer.
Read a CDouble value from the memory location pointer. This is equivalent to the C expression *((double*) pointer).
Write a CDouble value to the memory location pointer. This is equivalent to the C expression *((double*) pointer) = value, pointer.
These functions and constants are written in pure Mars, and their use is optional. However, they are helpful in dealing with converting data between Mars and C.
The CChar value 0 (num_cuchar('\0')). This is equivalent to the C expression '\0'.
Converts a Mars string into a C string (a pointer to a contiguous array of bytes, terminated with the byte value 0). This allocates sufficient memory for the C string using malloc, and copies each value into a single byte of the buffer, also writing the 0 byte at the end. Returns a pointer to the allocated C string.
It is an error if any element of string is non-integral or outside the range [0, 255].
This returns a new pointer value every time it is called, even if given the same input.
Warning
If any element of the string is 0, it will be copied into the buffer without error, which will cause any code which expects a null-terminated string to consider the first 0 byte to be the end of the string. This can potentially cause security vulnerabilities.
Converts a C string (a pointer to a contiguous array of bytes, terminated with the byte value 0) into a Mars string. The bytes in the array cstr are read one after another, and copied into a Mars array until a 0 byte is detected. The 0 byte is not copied into the Mars array.
Behaviour is undefined if cstr is not a valid pointer, or if it does not contain a 0 byte anywhere in its allocated length. cptr_string will keep reading bytes until it detects a 0 byte.