• Stars
    star
    136
  • Rank 267,670 (Top 6 %)
  • Language
    C++
  • License
    Other
  • Created almost 6 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Tiny Modern C++ Header Brings Unified Interface for Different Languages

Svar, A Tiny Modern C++ Header Brings Unified Interface for Different Languages


Build Status Build Status Codacy Badge License Version

Paper Introduction: https://arxiv.org/abs/2108.08464 , if you wanna use Svar in your research, please cite:

@misc{zhao2021svar,
      title={Svar: A Tiny C++ Header Brings Unified Interface for Multiple programming Languages}, 
      author={Yong Zhao and Pengcheng Zhao and Shibiao Xu and Lin Chen and Pengcheng Han and Shuhui Bu and Hongkai Jiang},
      year={2021},
      eprint={2108.08464},
      archivePrefix={arXiv},
      primaryClass={cs.PL}
}

Quick start

1. Bind C++ to hello.so 2. Import by C++ 3. Import by Python
#include <Svar.h>
 
void say(std::string v){
  std::cerr<<v<<std::endl;
}
REGISTER_SVAR_MODULE(hello)
{
  svar["say"] = say;
}
EXPORT_SVAR_INSTANCE
#include <Svar.h>
 
auto m=svar.import("hello");
int main(){
  m["say"]("hello world");
  return 0;
}
import svar
hello = svar.load("hello")
hello.say("hello world")
4. Import by Javascript 5. C++ import Python 6. Javascript import Python
svar = require('./svar')
hello =  svar('hello')
hello.say("hello world")
#include <Svar.h>
 
auto py=svar.import("svarpy");
int main(){
  auto os = py["import]("os");
  std::cout<<"Pid is:"
  <<os["getpid"]();
  return 0;
}
svar=require("./svar")
python=svar("svarpy")
os=python.import("os")
print("Pid is", os.getpid())

Why Svar?

Svar is a powerful tiny modern c++ header implemented the following functionals:

  • JSON with buffer: Svar natually support JSON, but more than JSON, where JSON is only a subset of Svar data structure.
  • Argument parsing: Svar manages parameter in tree style, so that configuration in JSON format can be supported.
  • More than std::any after c++17: Svar is able to hold everything, including variables, functions, and classes. They can be used directly without declare header, just like writing Python or JavaScript!
  • A general plugin form. The released library comes with documentation, making *.h header file interface description unnecessary.
  • Auto multi-languages api. By Using Svar, your C++ library can be called easily with different languages like C++, Java, Python and Javascript.

Compile and Install

Obtain source code from github

git clone https://github.com/zdzhaoyong/Svar

Compile the source code with cmake:

cd Svar
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make
sudo make install

Usages

Perform tests

Usage help:

svar --help
svar tests

Use Svar like JSON

Svar natually support JSON and here is some basic usage demo:

    Svar null=nullptr;
    Svar b=false;
    Svar i=1;
    Svar d=2.1;
    Svar s="hello world";
    Svar v={1,2,3};
    Svar m={{"b",false},{"s","hello world"},{"n",nullptr},{"u",Svar()}};

    Svar obj;
    obj["m"]=m;
    obj["pi"]=3.14159;

    std::cout<<obj<<std::endl;

    if(s.is<std::string>()) // use is to check type
        std::cout<<"raw string is "<<s.as<std::string>()<<std::endl; // use as to cast, never throw

    double db=i.castAs<double>();// use castAs, this may throw SvarException

    for(auto it:v) std::cout<<it<<std::endl;

    for(std::pair<std::string,Svar> it:m) std::cout<<it.first<<":"<<it.second<<std::endl;

    std::string json=m.dump_json();
    m=Svar::parse_json(json);

You can run the above code with:

svar sample -json

Use Svar for Argument Parsing

Svar provides argument parsing functional with JSON configuration loading. Here is a small demo shows how to use Svar for argument parsing:


int main(int argc,char** argv)
{
    svar.parseMain(argc,argv);

    int  argInt=svar.arg<int>("i",0,"This is a demo int parameter");
    bool bv=svar.arg("b.dump",false,"Svar supports tree item assign");
    Svar m =svar.arg("obj",Svar(),"Svar support json parameter");

    if(svar.get<bool>("help",false)){
        svar.help();
        return 0;
    }
    if(svar["b"]["dump"].as<bool>())
        std::cerr<<svar;
    return 0;
}

When you use "--help" or "-help", the terminal should show the below introduction:

-> sample_use --help
Usage:
sample_use [--help] [-conf configure_file] [-arg_name arg_value]...

Using Svar supported argument parsing. The following table listed several argume
nt introductions.

Argument        Type(default->setted)           Introduction
--------------------------------------------------------------------------------
-i              int(0)                          This is a demo int parameter
-b.dump         bool(false)                     Svar supports tree item assign
-obj            svar(undefined)                 Svar support json parameter
-conf           str("Default.cfg")              The default configure file going
                                                 to parse.
-help           bool(false->true)               Show the help information.

"help" and "conf" is two default parameters and users can use "conf" to load JSON file for configuration loading.

Svar supports the following parsing styles:

  • "-arg value": two '-' such as "--arg value" is the same
  • "-arg=value": two "--" such as "--arg=value" is the same
  • "arg=value"
  • "-arg" : this is the same with "arg=true", but the next argument should not be a value

Svar supports to use brief Json instead of strict Json:

sample_use -b.dump -obj '{a:1,b:false}'

Svar Holding Everything

Hold Class Instances

Svar support to hold different values:

    struct A{int a,b,c;}; // define a struct

    A a={1,2,3};
    Svar avar=a;      // support directly value copy assign
    Svar aptrvar=&a;  // support pointer value assign
    Svar uptrvar=std::unique_ptr<A>(new A({2,3,4}));
    Svar sptrvar=std::shared_ptr<A>(new A({2,3,4})); // support shared_ptr lvalue

    std::cout<<avar.as<A>().a<<std::endl;
    std::cout<<aptrvar.as<A>().a<<std::endl;
    std::cout<<uptrvar.as<A>().a<<std::endl;
    std::cout<<sptrvar.as<A>().a<<std::endl;

    std::cout<<avar.castAs<A*>()->b<<std::endl;
    std::cout<<aptrvar.as<A*>()->b<<std::endl;
    std::cout<<uptrvar.castAs<A*>()->b<<std::endl;
    std::cout<<sptrvar.castAs<A*>()->b<<std::endl;

    std::cout<<uptrvar.as<std::unique_ptr<A>>()->b<<std::endl;
    std::cout<<sptrvar.as<std::shared_ptr<A>>()->b<<std::endl;

Run the above sample with 'svar sample -instance'.

Hold Functions

void c_func_demo(Svar arg){
    std::cout<<"Calling a c_func with arg "<<arg<<std::endl;
}

int sample_func(){
    Svar c_func=c_func_demo;
    c_func("I love Svar");

    Svar lambda=[](std::string arg){std::cout<<arg<<std::endl;};
    lambda("Using a lambda");

    Svar member_func(&SvarBuffer::md5);
    std::cout<<"Obtain md5 with member function: "
            <<member_func(SvarBuffer(3)).as<std::string>()<<std::endl;

    return 0;
}

Run the above sample with 'svar sample -func'.

Hold and use a Class


class Person{
public:
    Person(int age,std::string name)
        : _age(age),_name(name){
        all_person()[name]=_age;
    }

    virtual std::string intro()const{
        return Svar({{"Person",{_age,_name}}}).dump_json();
    }

    int age()const{return _age;}

    static Svar& all_person(){
        static Svar all;
        return all;
    }

    int _age;
    std::string _name;
};

class Student: public Person{
public:
    Student(int age,std::string name,std::string school)
        : Person(age,name),_school(school){}

    virtual std::string intro()const{
        return Svar({{"Student",{_age,_name,_school}}}).dump_json();
    }

    void setSchool(const std::string& school){
        _school=school;
    }

    std::string _school;
};

{
    // define the class to svar
    Class<Person>("Person","The base class")
            .construct<int,std::string>()
            .def("intro",&Person::intro)
            .def_static("all",&Person::all_person)
            .def("age",&Person::age)
            .def_readonly("name",&Person::_name,"The name of a person");

    Class<Student>("Student","The derived class")
            .construct<int,std::string,std::string>()
            .inherit<Person>()
            .def("intro",&Student::intro)
            .def("setSchool",&Student::setSchool)
            .def("getSchool",[](Student& self){return self._school;})
            .def_readwrite("school",&Student::_school,"The school of a student");

    // use the class with svar
    Svar Person=svar["Person"];
    Svar Student=svar["Student"];
    std::cout<<Person.as<SvarClass>();
    std::cout<<Student.as<SvarClass>();

    Svar father=Person(40,"father");
    Svar mother=Person(39,"mother");
    Svar sister=Student(15,"sister","high");
    Svar me    =Student(13,"me","juniar");
    me.call("setSchool","school1");

    std::cout<<"all:"<<Person.call("all")<<std::endl;
    std::cout<<father.call("intro").as<std::string>()<<std::endl;
    std::cout<<sister.call("intro").as<std::string>()<<std::endl;
    std::cout<<mother.call("age")<<std::endl;
    std::cout<<me.call("age")<<std::endl;
    std::cout<<sister.call("getSchool")<<std::endl;
    std::cout<<me.call("getSchool")<<std::endl;

    me.set<std::string>("school","school2");
    std::cout<<me.get<std::string>("school","")<<std::endl;
}

Run the above code with "svar sample -module"

Create and Use a Svar Module

The last page shows that we can use functions and classes with Svar. What if we expose only Svar instead of headers for a c++ shared library? Yes we don't need headers any more! We call that shared library Svar module, which can be imported and call directly.

Create a Svar module

#include "Svar.h"

using namespace GSLAM;

int add(int a,int b){
    return a+b;
}

class Person{
public:
    Person(int age,std::string name)
        : _age(age),_name(name){
        all_person()[name]=_age;
    }

    virtual std::string intro()const{
        return Svar({{"Person",{_age,_name}}}).dump_json();
    }

    int age()const{return _age;}

    static Svar& all_person(){
        static Svar all;
        return all;
    }

    int _age;
    std::string _name;
};

class Student: public Person{
public:
    Student(int age,std::string name,std::string school)
        : Person(age,name),_school(school){}

    virtual std::string intro()const{
        return Svar({{"Student",{_age,_name,_school}}}).dump_json();
    }

    void setSchool(const std::string& school){
        _school=school;
    }

    std::string _school;
};

REGISTER_SVAR_MODULE(sample)// see, so easy, haha
{
    svar["__name__"]="sample_module";
    svar["__doc__"]="This is a demo to show how to export a module using svar.";
    svar["add"]=add;

    Class<Person>("Person","The base class")
            .construct<int,std::string>()
            .def("intro",&Person::intro)
            .def_static("all",&Person::all_person)
            .def("age",&Person::age)
            .def_readonly("name",&Person::_name,"The name of a person");

    Class<Student>("Student","The derived class")
            .construct<int,std::string,std::string>()
            .inherit<Person>()
            .def("intro",&Student::intro)
            .def("setSchool",&Student::setSchool)
            .def("getSchool",[](Student& self){return self._school;})
            .def_readwrite("school",&Student::_school,"The school of a student");
}

EXPORT_SVAR_INSTANCE // export the symbol of Svar::instance

We compile the above code to a shared library "libsample_module.so" or "sample_module.dll".

The Svar Module Documentation

Show the context of the sample plugin module:

# Show the structure of a plugin
svar doc -plugin libsample_module.so
# Show the documentation of a named class
svar doc -plugin libsample_module.so -key Person
# Show the documentation of a named function
svar doc -plugin libsample_module.so -key add

Import and Use a Svar Module

For the Svar module, we can import and use them in different languages! Here we show how to use it in c++, source code is available in file "src/sample/main.cpp".

    Svar sampleModule=Registry::load("sample_module");

    Svar Person=sampleModule["Person"];
    Svar Student=sampleModule["Student"];
    std::cout<<Person.as<SvarClass>();
    std::cout<<Student.as<SvarClass>();

    Svar father=Person(40,"father");
    Svar mother=Person(39,"mother");
    Svar sister=Student(15,"sister","high");
    Svar me    =Student(13,"me","juniar");
    me.call("setSchool","school1");

    std::cout<<"all:"<<Person.call("all")<<std::endl;
    std::cout<<father.call("intro").as<std::string>()<<std::endl;
    std::cout<<sister.call("intro").as<std::string>()<<std::endl;
    std::cout<<mother.call("age")<<std::endl;
    std::cout<<me.call("age")<<std::endl;
    std::cout<<sister.call("getSchool")<<std::endl;
    std::cout<<me.call("getSchool")<<std::endl;

    me.set<std::string>("school","school2");
    std::cout<<me.get<std::string>("school","")<<std::endl;

Run the above code with "svar sample -module".

Use Svar Module in Other Languages

The last page shows how to use a Svar module in c++. Can the module also be imported by other languages?

Yes!Yes!Yes! But we only implemented the python3 interface now, if you are familar with bindings, please contact me and we can cooperate on this!

Use the Sample Module with Python

Firstly, please install the svar module with pip3:

cd Svar
pip3 install .

Then, we can run the following python script with python3:

import svar

s=svar.load('sample_module')

father=s.Person(40,'father') # constructor
mother=s.Person(39,'mother')
sister=s.Student(15,'sister','high')
me=s.Student(13,'me','juniar')

me.setSchool('school1')

print("all:",s.Person.all())

print(father.intro())
print(sister.intro())
print(mother.age())
#print(me.age()) # TODO: derivation is not implemented yet by the python binding
print(sister.getSchool())
print(me.getSchool())

print(father.name) # property
print(me.school)

Use the Sample Module with NodeJS (Tested on Ubuntu 16.04)

Firstly, please install the svar module with npm:

cd Svar/src/nodejs
npm install .

Then, we can run the demo javascript with node:

node sample_module.js

The file content is listed as below:

s    = require('bindings')('svar')('sample_module')

console.log(s)

p = new s.Person(3,'zy')
console.log(p.age())
console.log(s.Person.all())

student = new s.Student(3,"zy","npu")

console.log(student.school,student.intro())

Supported Compilers

Currently, the following compilers are known to work:

GCC 4.8 - 9.2 (and possibly later)

Clang 3.4 - 9.0 (and possibly later)

Intel C++ Compiler 17.0.2 (and possibly later)

Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)

Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)

Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later)

Contact and Donation

Any question or suggestion please contact:

Yong Zhao : [email protected]

Svar is a personal free project with BSD license, if you like it, donation is accepted with the following approaches to support the author:

Wechat Alipay PayPal
paypal

License

Copyright (c) 2018 Northwestern Polytechnical University, Yong Zhao. All rights reserved.

This software was developed by the Yong Zhao at Northwestern Polytechnical University.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must
display the following acknowledgement: This product includes software developed
by Northwestern Polytechnical University and its contributors.
4. Neither the name of the University nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

More Repositories

1

GSLAM

A General Simultaneous Localization and Mapping Framework which supports feature based or direct method and different sensors including monocular camera, RGB-D sensors or any other input types can be handled.
C++
908
star
2

Map2DFusion

This is an open-source implementation of paper: Real-time Incremental UAV Image Mosaicing based on Monocular SLAM.
C++
295
star
3

SummerCamp2018

智能系统实验室-2018新人暑期培训计划
C++
144
star
4

PICMake

你还在学CMake的过程中毫无头绪吗?你还在为复杂程序库依赖发愁吗?你是否觉得原生CMake的编写冗余而低效?那就快来学习和使用PICMake吧!只需要一行,无论是可执行,动态库还是静态库,轻松搞定!同时高效支持多目标,复杂库的编译安装,从此告别大量冗余CMake代码,专注开发核心应用程序,编译不再愁! 例如下面是使用PICMake编译一个依赖OpenGL的可执行文件,只需要一行!
C++
80
star
5

RTMapperSDK

RTMapperSDK is the c++ sdk for application development like RTMapper. It handle images captured with UAVs and outputs ortho mosaic at realtime.
C
28
star
6

highstitch

Code for paper: HighStitch: High Altitude Georeferenced Aerial Images Stitching for Rocking Telephoto Lens
C++
16
star
7

GSLAM-TheiaSfM

C++
7
star
8

synergy

Free version of synergy for ubuntu and windows
Shell
7
star
9

svar_rosbridge

A C++11 based cross-language (C++/Python/Node-JS) rosbridge client with CBOR support.
C++
7
star
10

VideoCompare

This application is designed to find the differences between two videos. The reference video is indexed with BoWs and so that the second video is able to find the best match keyframe from reference video very fast.
C++
7
star
11

GSLAM-VINS

The VINS-Mobile implementation plugin for GSLAM
C++
5
star
12

EICAM

The EICAM is the a part of PIL library, which includes some pretty useful tools for C++ programing espesially in the areas of moblile robotics and CV (computer vision). Since cameras projection and unprojection actions are often needed in CV or other area such as Robot localization like SLAM (simultaneous localization and mapping), we provided EICAM for efficient implimentation of different camera models including PinHole, ATAN, OpenCV, OCAM .etc.
C++
5
star
13

PIL

The PIL library includes some pretty useful tools for C++ programing espesially in the areas of moblile robotics and CV (computer vision), includes ThreadBase,Svar,TImer,SE3 in PI_Base and hardwares support like Cameras, GPS and so on.
C++
3
star
14

highstitch-dataset

The NPU HighStitch Dataset
3
star
15

phantom3-village-kfs

A sample sequence for Map2DFusion.
3
star
16

GSLAM_OptimizerPBA

An optimizer plugin base on PBA for GSLAM later then version 2.1.0, which implement parallel bundle adjust with GPU or multi-core CPU.
C++
3
star
17

svar_nsq

C++
3
star
18

ShellToolkit

This package is aim to help Linux/UNIX users to collect their own bash shells and got better experience. You can doing a lot of things easily by this tool, such as ‘cd’ to a folder faster, automatically config your Makefile environment, help you remember program history thing and complete your parameters later, and so on. Enjoy it!
Shell
3
star
19

svar_monitor

Small c++ svar module to monitor the CPU, Memory and IO usages.
C
2
star
20

Messenger

An alternative option to replace ROS message transfering with single header from GSLAM.
CMake
2
star
21

GSLAM-JS

The Javascript wapper of GSLAM.
C++
1
star
22

EssentialTracker

C++
1
star
23

DatasetNetwork

C++
1
star
24

GBoW

GSLAM implementation of DBoW, with only headers and removed dependency of OpenCV.
C++
1
star
25

fengniao

1
star
26

svar_messenger

A svar module implemented ros like pub/sub.
C++
1
star