# Svar **Repository Path**: pi-lab/Svar ## Basic Information - **Project Name**: Svar - **Description**: A Flexible C++ Variable Container - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 4 - **Created**: 2021-03-10 - **Last Updated**: 2025-08-07 ## Categories & Tags **Categories**: utils **Tags**: None ## README # Svar - A Flexible C++ Variable Container Svar is a powerful tiny modern c++ header implemented variable container and unified interface for different languages. To use the package, the best way is to use the example codes: * [samples](src/Svar_packages/sample/sample.cpp) * [sample module](src/modules/sample_module/module.cpp) Related projects: * [Svar-allinone](https://gitee.com/pi-lab/Svar-allinone) - Svar模块 * [GSLAM](https://gitee.com/pi-lab/GSLAM) - GSLAM,视觉计算库 * [PI-Mavlink](https://gitee.com/pi-lab/pi-mavlink) - Mavlink,无人机管理,集群 * [code_cook](https://gitee.com/pi-lab/code_cook) - 代码实例 Svar documentation index - [Why Svar](#why-svar) - [Compile and Install](#compile-and-install) - [Usages](#usages) - [Perform tests](#perform-tests) - [Use Svar like JSON](#use-svar-like-json) - [Use Svar for Argument Parsing](#use-svar-for-argument-parsing) - [Svar Holding Everything](#svar-holding-everything) - [Hold Various Variables](#hold-various-variables) - [Hold Class Instances](#hold-class-instances) - [Hold Functions](#hold-functions) - [Hold and Use a Class](#hold-and-use-a-class) - [Create and Use a Svar Module](#create-and-use-a-svar-module) - [Create a Svar Module](#create-a-svar-module) - [The Svar Module Documentation](#the-svar-module-documentation) - [Import and Use a Svar Module](#import-and-use-a-svar-module) - [Use Svar Module in Other Languages](#use-svar-module-in-other-languages) - [References](#references) ## 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://gitee.com/pi-lab/Svar ``` Compile the source code with cmake: ``` cd Svar mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release make sudo make install ``` ## Usages Some example usages can be found at: * [samples](src/Svar_packages/sample/sample.cpp) * [sample module](src/modules/sample_module/module.cpp) ### Perform tests Usage help: ``` svar --help ``` ``` svar tests ``` ### Use Svar like JSON Svar natually support JSON and here is some basic usage demo: ```c++ 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<()) // use is to check type std::cout<<"raw string is "<()<();// use castAs, this may throw SvarException for(auto it:v) std::cout< it:m) std::cout<("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("help",false)){ svar.help(); return 0; } if(svar["b"]["dump"].as()) std::cerr< 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 Various Variables Svar support to hold various variables: ```c++ ///////////////////////////////////// /// variable set/get ///////////////////////////////////// // set any variable to svar svar["obj_len"] = 100; svar["obj_ptr"] = new int[100]; // get the original type int pn = svar["obj_len"].castAs(); int *p = svar["obj_ptr"].castAs(); printf("obj_len = %d, obj_ptr = %x\n", pn, p); for(int i=0; i it:svar) std::cout< UAV* { return new UAV_Mavlink;}); uav["XY"] = Svar::lambda([]() -> UAV* { return new UAV_XY;}); Svar& uav_creator = svar["uav"]; UAV *u1 = uav_creator["mavlink"]().castAs(); UAV *u2 = uav_creator["XY"]().castAs(); printf("u1->type() = %s\n", u1->type().c_str()); printf("u2->type() = %s\n", u2->type().c_str()); ``` Run the above sample with `svar sample -variable`. #### Hold Class Instances Svar support to hold different values: ```c++ 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(new A({2,3,4})); Svar sptrvar=std::shared_ptr(new A({2,3,4})); // support shared_ptr lvalue std::cout<().a<().a<().a<().a<()->b<()->b<()->b<()->b<>()->b<>()->b<()<("Person","The base class") .construct() .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","The derived class") .construct() .inherit() .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<(); std::cout<(); 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:"<()<()<("school","school2"); std::cout<("school","")<` 等类型赋值给Svar,则转变成 `std::vector`,因此需要手动转换,示例代码如下: ```c++ sv::Svar msg; std::vector buf(100); if( 1 ) { msg["payload"] = buf; std::cout << msg.dump_json() << std::endl; sv::Svar p = msg["payload"]; std::vector arr = p.as>(); std::vector buf2; buf2.resize(arr.size()); for(int i=0; i(); } } ``` 如果不想这么复杂的转换,在同一个进程内,可以传递指针,示例代码如下: ```c++ sv::Svar msg; std::vector buf(100); if( 1 ) { msg["payload"] = &buf; std::cout << msg.dump_json() << std::endl; sv::Svar p = msg["payload"]; std::vector *pl = p.as*>(); printf("payload.size() = %d\n", (int)pl->size()); } ``` ### 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 ```c++ #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","The base class") .construct() .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","The derived class") .construct() .inherit() .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: ```bash # 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". ```c++ Svar sampleModule=Registry::load("sample_module"); Svar Person=sampleModule["Person"]; Svar Student=sampleModule["Student"]; std::cout<(); std::cout<(); 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:"<()<()<("school","school2"); std::cout<("school","")<