C++ example
A simple C++ application that checks-out a single license
QuidLM discovers, validates, and parses licenses. To take advantage of that functionality in your application, you need to
-
Initialize QuidLM. This is done by creating a
qlm::LicenseSourceobject. You can use this opportunity to provide the user's credentials. They come into play because licenses can be configured to be available only to a subset of users. You may set the user email and password tonullptror omit those arguments if you do not intend to use this functionality. If you initialize the license system without specifying user email and password, QuidLM will not provide those licenses to your application.const char *user_email = nullptr, *password = nullptr; qlm::LicenseSource source(user_email, password);If initialization encounters an error, the
qlm::LicenseInitErrorexception is thrown, and its.what()member function provides a message explaining the issue. -
Grab the license. The
source.checkout_licensemember function takes two inputs - the license name and the version. The license name is typically just the name of your product. The license version, if provided, should be in themajor.minorformat. QuidLM treats this input as the minimum license version that your application is willing to accept. Typically, you pass your application’s current version for this parameter. This ensures that newer licenses enable older applications, but not vice versa — which is usually the desired behavior. If that is not what you want, you can hard‑code the version to "1.0" or another constant.const char* product_name = "MyProduct", min_version = "3.1"; qlm::License license = source.checkout_license(product_name, min_version);If the requested license is not available,
qlm::LicenseCheckoutErrorexception is thrown, and your application may want to catch it to explain the error to the user and exit. Otherwise, theqlm::Licenseobject contains useful information about the license, such as its expiration date (license.expiry()) and custom parameters - a set of key-value pairs, which you, the developer, can use to set the application's behavior. For example, you can enable some features based on the presence of certain parameters: e.g.,trial-license=truemay prompt your application to display the "trial copy" badge. One other typical use of such a parameter is to limit the application performance, as inmax-threads=10.The member functions of
qlm::Licenseare defined and explained in thelicense_api.hppheader file.qlm::Licenseobjects are copyable, and the copies represent the same license. The license is released when all copies (including the original) are destroyed.
The above are the required parts, but you can also take advantage of optional features, such as logging and
license revocation. These additional features are demonstrated in the sample applications shipped with QuidLM.
The cpp_client application is a more fully featured example, which can also
be used for testing. It is a command line application that checks out the license specified
on the command line for the specified number of seconds and prints licensing information. The
comments in the source code explain standard functionality, such as initialization and license checkout,
and introduce logging and license revocation. The example is cross-platform - there are
several #ifdef _MSC_VER sections to support both Windows and UNIX systems.
/// Cpp_client application: grab the specified license for
/// the specified length of time and print the licensing information.
#include <atomic> // std::atomic<bool>
#include <chrono> // sleep duration
#include <cstdlib> // std::exit
#include <iomanip>
#include <iostream>
#include <string>
#include <thread> // sleep_for
#include "license_api.hpp"
std::atomic<bool> dead_license = false;
/// When the license is revoked, the application should react by saving the state, notifying the user, and exiting.
/// The function below is automatically called, for example, when the network connection to licensing service breaks.
/// This function is called from a separate thread, so it should be careful when accessing the global state.
/// For example, it can let the main thread (and potentially other threads) know by setting the global atomic flag.
/// Note that it should not call the standard library's exit function, as doing that in a thread is an undefined behavior.
/// For the purpose of demonstration, here we set the flag and print the message to the stderr.
void revocation_callback(const license_info_t* license_handle, enum revocation_reason reason)
{
dead_license = true;
std::cerr << "This application's " << license_handle->product_name << " license has been revoked: " << qlm::revocation_reason(reason) << ".\n";
}
/// Check out the license for the specified product with the given version number (or higher),
/// print the license information, wait the specified number of seconds, and return.
int main(int argc, const char* argv[])
try {
if (argc < 2)
throw std::runtime_error(
"Expected some inputs on the command line.\n\n"
" product_name: the product that you need the license for [required]\n"
" min_version: the minimum version of the product, in the major.minor format [1.0]\n"
" duration: exit application after this many seconds [2]\n\n");
const char* const product_name = argv[1];
const char* const product_version = argc < 3 ? "1.0" : argv[2];
const int duration = argc < 4 ? 2 : std::stoi(argv[3]);
// optional reaction to revoked licenses
qlm::set_revocation_handler(revocation_callback);
// set a verbose log level for debugging
// set_log_level(debug);
// alternatively, set the environment variable: QLM_LOG_LEVEL=debug
// Licenses can be configured to be available only to a set of users.
// If you initialize the license system without specifying the user's email and password, you will never receive those licenses.
const char *user_email = nullptr, *password = nullptr;
qlm::LicenseSource source(user_email, password);
{
auto license = source.checkout_license(product_name, product_version);
std::cout << "Got license for product version " << license.product_version() << ".\n"
"Expiring " << license.expiry() << ".\n"
"Floating: " << (license.is_floating() ? "true" : "false") << ".\n"
"License properties:\n";
for (const auto& name_value : license.properties())
std::cout << name_value.first << ": " << name_value.second << "\n";
std::this_thread::sleep_for(std::chrono::seconds(duration));
std::cout << "Returning the license\n";
// The license is returned when the variable is destroyed
}
std::cout << "Exiting\n";
return 0;
} catch (const qlm::LicenseCheckoutError& e) {
std::cerr << "License checkout error: " << e.what() << "\n";
return 2;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
return 1;
}