MMU

README
Login

README

MMU is a small utility library that provides abstractions over memory mapped files.

Installation

To build MMU from source you will need a C++14 compiler and CMake.

Usage

MMU offers the following utilities:

Here's a simple usage example to get you started:

#include <cstdio>
#include <string>
#include <algorithm>
#include <MMU/MMU.hpp>

int main(int nargs, const char **args) {
  MMU::set_program_name(nargs > 0 ? args[0] : __FUNCTION__);
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
  try
# endif
  {
    auto array = MMU::file_array<const char>(__FILE__);
    MMU_ASSERT(array.contiguous());
    MMU_ASSERT(array.begin() != array.end());

    auto slice = array.slice(1, 7, 2);
    MMU_ASSERT(!slice.contiguous());
    MMU_ASSERT(std::equal(slice.begin(), slice.end(), "icue<sd"));

    typedef std::basic_string<
      char, std::char_traits<char>,
      MMU::Allocator<char>
    > mmu_string_t;
    auto pool = MMU::buffer_pool("buffer_pool.d");
    mmu_string_t hello("Hello world!", pool);
    MMU_ASSERT(hello[6] == 'w');

    auto libc = MMU::shared_library(nullptr);
    auto puts = libc->get<void, const char *>("puts");
    if (MMU_UNLIKELY(!puts)) MMU_ASSERT_ERROR(libc->last_error());
    puts(hello.c_str());

    return 0;
  }
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
  catch (const std::exception &exn) {
    fprintf(stderr, "%s: Error: %s\n", MMU::program_name(), exn.what());
    return 1;
  }
# endif
}

Loading Managed Assemblies

The function MMU::managed_library behaves similar to MMU::shared_library on the client side, taking the path to a .NET assembly it should load. The MMU::ILibrary object returned by the function can be used to retrieve native delegates from that assembly.

In the background, MMU::managed_library loads the hostfxr library and makes sure a suitable .NET runtime is attached to the process.

Support for this feature must be enabled when compiling MMU.

In case of managed assemblies, the symbol names passed to MMU::ILibrary::get or get_pointer have a certain structure: Namespace and class qualifiers separated by the usual dots must precede the static method name. In addition, a delegate type used to convert the method into a native function pointer can be specified, otherwise the method must be compatible with the signature int (void *, int32_t). Assembly qualifiers can be omitted from the types, in which case the basename of the loaded assembly is added automatically. So the full format of a symbol name is NAMESPACE.METHOD[, ASSEMBLY][: NAMESPACE.DELEGATE[, ASSEMBLY]].

If the literal string UnmanagedCallersOnly is given as the delegate type, the target method must be marked with the System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute and observe the associated rules.

Loading Libraries from Source

The function MMU::compiled_library behaves similar to MMU::shared_library (in fact it calls the latter eventually), but it takes a single source file as an argument and compiles it for you. The mechanism can even inject package dependencies into the build environment.

To work, CMake 4.1, the necessary compilers, and the used package managers have to be installed.

Dependency Comments

The special comments recognized by MMU::compiled_library all match the regular expression ^//([-+ILlr])\s*("[^"]*"|\S+):

//I "PATH"

Add a fixed include PATH to the C(++) compiler's command line.

//L "PATH"

Add a fixed library PATH to the C(++) compiler's command line.

//l "NAME"

Add a library called NAME to the linker's command line.

//r "pkg-config: NAME, VERSION"

Add a dependency on a pkg-config package. The version specification may be omitted.

If the dependency is written as //r "@pkg-config: …", it is processed with cmake_pkg_config(POPULATE …) rather than cmake_pkg_config(IMPORT …).

//r "conan: NAME, VERSION"

Add a dependency on a Conan package.

If the dependency is written as //r "@conan: …", it is added to the conanfile.txt, but not referenced in CMake. This can be useful for packages with different names for the package manager artifact, the conceptual CMake package, and the CMake library target.

//r "nuget: NAME, VERSION"

Add a dependency on a NuGet package. The version specification may be omitted.

//r "NAME, VERSION"

Add a dependency on a CMake package. The version specification may be omitted.

If the package name has the form FIND_NAME::LINK_NAME, the FIND_NAME is used in find_package calls, while the full name is used in target_link_libraries calls.

//+CONDITION

The effect of following magic comments will be wrapped in a CMake if(CONDITION) block.

//-CONDITION

Generates a CMake endif(CONDITION) statement. The condition must be empty, or match the last open condition block.

Condition blocks left open are closed automatically after the effects of all magic comments have been issued.