A library for C++ reflection and introspection
add_prebuild_command()
cmake command in utils.cmake
was invoking add_dependencies()
even when the target has no dependencies.DRLParser
) was ignoring blacklist rules in nested pathsDRLParser
is packaged with executable permissions enabledThis release finishes with the cleanup and refactoring work I have been doing to the API. Now the API has alll the features I want to show in the Meeting C++ 2016 talk
The current API docs can be seen here (There are also experimental Standardese docs here).
The release includes a packaged version of siplasplas, with all the cmake scripts to work (See installation in the readme) and siplasplas modules built as dynamic libraries using GCC 6.1.2 on Arch Linux.
This is not a production ready release, but a packaged version of siplasplas to check the configuration and behavior of siplasplas when not being used from sources. The main purpose of this release is to check:
include/
dir, the prebuilt siplasplas modules in a lib/
dir, and the reflection parser tools in bin/
. The package also contains a set of cmake scripts that may be used for easy configuration of siplasplas reflection, cmake/
dir.cmake/siplasplas.cmake
script. Also, the siplasplas project includes a bootstrap.cmake
script that can be used to automatically download and configure siplasplas by just including that file in your project.This packaged version of siplasplas supports:
This release doesn't provide:
Download bootstrap.cmake
file from the master branch and include it in your project CMakeLists.txt
as follows:
# URL to the release package:
set(SIPLASPLAS_PACKAGE_URL "https://github.com/Manu343726/siplasplas/releases/download/0.0.0/siplasplas-master-Clang-3_8_1-Debug-dynamic.tar.gz")
# Libclang version used by siplasplas reflection parser:
set(SIPLASPLAS_LIBCLANG_VERSION 3.8.1)
# Download libclang automatically (Easier than setting up libclang in your system):
set(SIPLASPLAS_DOWNLOAD_LIBCLANG ON)
# Install reflection parser Python dependencies automatically (Requires [pip](https://pip.pypa.io/en/stable/) for python 2.7)
set(SIPLASPLAS_INSTALL_DRLPARSER_DEPENDENCIES ON)
include(bootstrap.cmake)
To enable static reflection, invoke configure_siplasplas_reflection()
cmake command with your target as parameter:
add_library(MyLib mylib.cpp)
target_include_directories(MyLib PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_compile_options(MyLib PRIVATE -std=c++11)
configure_siplasplas_reflection(MyLib)
This will install a pre-build target to run DRLParser before building your library.
To make static reflection available for a header, include <reflection/[full path to the header]>
at the end of the header file:
// myProjectSourceDir/include/mylib.h
#ifndef MYLIB_H
#define MYLIB_H
namespace MyLib
{
class MyClass
{
public:
enum class Enum
{
FOO,
BAR,
QUUX
};
int doSomething(const std::string& param);
int i = 0;
};
}
#include <reflection/mylib.h>
#endif // MYLIB_H
Here's a link to the latest master
documentation of siplasplas: https://manu343726.github.io/siplasplas/doc/doxygen/master/modules.html (Standardese version here).
Please note the library is still on development and the documentation is incomplete. Feel free to open an issue reporting any problem you have with the docs.
siplasplas currently lacks proper documentation of its reflection API, but heres a brief example of how the static reflection API works:
#include "mylib.h"
#include <siplasplas/utility/fusion.hpp>
#include <siplasplas/utility/meta.hpp>
#include <siplasplas/utility/function_traits.hpp>
#include <iostream>
int main()
{
MyLib::MyClass myObject;
// Get reflection info about MyLib::MyClass class:
using MyClassInfo = cpp::static_reflection::Class<MyLib::MyClass>;
// cpp::static_reflection::Class exposes public aliases with typelists to the members of a class, currently:
// - Classes: Public member classes
// - Methods: Public non-static member functions
// - Fields: Public non-static member objects
// - Enums: Public enums (C enum or C++11 enum class)
//
// siplasplas provides a simple C++11 compatible metaprogramming lib in <siplasplas/utility/meta.hpp>
// with common metafunctions to manipulate typelists (get, append, split, cat, fold, fmap...) and other tmp
// utilities (void_t, logarithmic index_sequence, simple arithmetic, etc)
//
// The utility module also provides a fusion.hpp library with C++14 tools to do heterogeneous operations on
// parameter packs, type packs, etc; similar to boost::fusion
//
// Class<>::Methods returns a cpp::meta::list<> typelist with cpp::static_reflection::Function<> instances with the
// information of all the public methods of the class:
// - Function::get(): Returns a member function pointer to the function
// - Function::type: Returns the type of the member function, e.g. void(Class::*)(). This type can be queried with
// cpp::function_signature<>, cpp::function_args<>, cpp::function_arguments<> etc (In header siplasplas/utility/function_traits.hpp) to get the signature of the function.
// - Function::SourceInfo: Returns the instance of cpp::static_reflection::SourceInfo with the source information
// of the function declaration:
// Function::SourceInfo::spelling(): Returns the name of the member function, e.g. "doSomething"
// Function::SourceInfo::displayName(): Returns the display name (function name with signature)
// of the function, e-g. "void doSomething(const std::string& param)"
// Function::SourceInfo::fullName(): Returns the full qualified name of the member function, e.g. "MyLib::MyClass::doSomething"
// - class_type: Type of the class the member function belongs to, e.g. MyLib::MyClass
//
using Methods = MyClassInfo::Methods;
// Print information of all methods of the class:
cpp::foreach_type<Methods>([&](auto type)
{
// This is just a cool way to say "Give me the actual type", don't worry about this
// tmp stuff
using Method = cpp::meta::type_t<decltype(type)>;
std::cout << "Method: " << Method::spelling() << std::endl;
std::cout << " Number of arguments: " << cpp::function_arguments<typename Method::type>::size << std::endl;
std::cout << " Const member function: " << std::boolalpha << cpp::function_kind<typename Method::type>() == cpp::FunctionSignature::CONST_MEMBER_FUNCTION << std::endl;
});
// cpp::static_reflection::Enum<> is the Class<> counterpart for enum types. It provides
// methods for de/serialization of enum values to/from strings (Constexpr in C++14 only),
// The set of enum values, the number of enum values, etc:
constexpr auto enumValue = cpp::static_reflection::Enum<MyLib::MyClass::Enum>::fromString("FOO");
static_assert(enumValue == MyLib::MyClass::Enum::FOO, "???");
}