C++
nanoql's C++ layer, nanoql.hpp, is C++17 over the C interface: objects that release their handles, refusals thrown
as exceptions, nanoql's type names and QuantLib's member names (curve.discount(5.0)). It ships in each platform's C
archive, for Windows x64 and Arm64, Linux x64 and Arm64 and macOS on Apple silicon, with a CMake package.
The bindings guide's "C and C++" section gives its rules: names, objects, values, defaults and
overloads, errors. Coming from QuantLib's C++, the migration guide pairs its code
with nanoql's.
Install
Unpack the archive for your platform from the release,
nanoql-<version>-win-x64-c-api.zip or nanoql-<version>-linux-x64-c-api.tar.xz. It holds:
include/:nanoql.h, the C interface, andnanoql.hpp, the C++ layer over it;lib/: the library,nanoql.dllwith its import librarynanoql.libon Windows orlibnanoql.soon Linux, andcmake/nanoql/, the CMake package;- the notices:
LICENSE,NOTICE,THIRD_PARTY_NOTICES.mdand the .NET runtime's two, which the library carries.
CMake
Give CMake the archive's folder and link nanoql::cpp:
cmake_minimum_required(VERSION 3.21)
project(app CXX)
find_package(nanoql 2.1 CONFIG REQUIRED)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE nanoql::cpp)
cmake -S . -B build -DCMAKE_PREFIX_PATH=<the archive's folder>
cmake --build build --config Release
nanoql::cpp brings C++17 and nanoql::c, the library and include/; a C program links nanoql::c alone. A
request for a version takes this release or an earlier one of its major version, as CMake's SameMajorVersion rule
has it, version ranges included.
Windows: a program finds
nanoql.dllbeside it. A copy after the build puts it there:add_custom_command(TARGET app POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:app> $<TARGET_FILE_DIR:app> COMMAND_EXPAND_LISTS)Linux: a program run in its build tree finds
libnanoql.soby the run path CMake gives it; one installed or copied elsewhere finds it byLD_LIBRARY_PATHor its own run path ($ORIGIN).
bindings/cpp/consumer/ in the repository is this project, with the program below; CI builds it through each
platform's archive with MSVC on Windows, and g++ and clang on Linux.
A first program
#include <cstdio>
#include <exception>
#include "nanoql.hpp"
using namespace nanoql;
int main()
{
FlatForward curve(Date(15, Month::March, 2023), 0.03, ConventionSet::quantLib().dayCounter("Actual365Fixed"));
std::printf("discount(1) = %.6f\n", curve.discount(1.0)); // 0.970446
try {
curve.discount(-1.0);
} catch (const std::exception& e) {
std::printf("refused: %s\n", e.what()); // refused: negative time (-1) given
}
}
Each object holds a handle to its nanoql object and releases it when it goes out of scope; liveHandles() counts the
handles still held. A refusal is nanoql::error, a std::runtime_error with the C interface's code, the parameter it
names and its type, and under it argument_error and handle_error.
Compile time
nanoql.hpp declares the whole library, about 98,600 lines. A translation unit that includes it takes about 5 s and
600 MB with g++ at -O2, so include it in few files, or precompile it:
target_precompile_headers(app PRIVATE <nanoql.hpp>)
Versions
A release's header works with that release's library. A program that loads a library installed apart from its header
checks nql_abi_version() == NQL_ABI_VERSION first. A minor release adds to the stable API and removes only what was
deprecated two releases and a year before, which the header marks [[deprecated]] meanwhile; the guide's
Versions gives the rule. A new overload can make a call that compiled ambiguous, as in any C++
library; naming the argument's type settles it.
The experimental API
Define NANOQL_EXPERIMENTAL before including the header, or with target_compile_definitions(app PRIVATE NANOQL_EXPERIMENTAL), to declare the experimental API beside the stable one. It may change in any release.
A library of your own
nanoql-bind builds a library holding nanoql's functions and an assembly
of yours, and writes its headers beside nanoql's: acme.h and acme.hpp, whose classes extend nanoql's
(acme::ExponentialCurve is a nanoql::YieldTermStructure). Its README gives the commands.
Without the C++ layer
C++ can include nanoql.h as it is, its declarations in extern "C", and call the C interface directly: the guide's
"The C ABI" gives its handles, status codes and values.