Siplasplas Versions Save

A library for C++ reflection and introspection

0.0.2-1

7 years ago
  • add_prebuild_command() cmake command in utils.cmake was invoking add_dependencies() even when the target has no dependencies.
  • Diego Rodriguez Losada Parser (DRLParser) was ignoring blacklist rules in nested paths
  • DRLParser is packaged with executable permissions enabled

0.0.2

7 years ago
  • Minor doc fixes
  • siplasplas-constexpr: constexpr algorithms and strings
  • ctti dependency updated
  • Typelist sorting
  • Protobuf static-reflection example
  • libclang setup fixes
  • cpp::TypeInfo traits set fixes
  • And more... (Look at the log, as I've done to write this changelog :P)

0.0.1

7 years ago

This 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.

0.0.0

7 years ago

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:

  • Packaging layout: We test if the installation layout defined by the siplasplas configuration works as expected. We currently distribute the siplasplas headers in an 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 tools: We also test if the cmake tools menctioned above work as expected with the packaged distribution. The goal is to be able to use siplasplas reflection by just downloading the package and including the 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.
  • static reflection on real world projects

This packaged version of siplasplas supports:

  • static reflection: The siplasplas-reflection-static module and its dependencies are header only and C++11 compatible. Also, the code generated by the reflection tool (DRLParser) is header only and C++11 compatible too.

This release doesn't provide:

  • Required includes of 3rdParty siplasplas dependencies: This means that any siplasplas module depending on an external dependency (Such as ctti, spdlog, or fmt) will not work in this release.
  • Reflection metadata headers: Some siplasplas modules use static reflection and rely on the metadata generated by siplasplas (Mainly siplasplas-fswatch and siplasplas-cmake). That headers are not included in this release.

Playing with this release

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.

Static reflection API

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, "???");
}