Svar
A Tiny Modern C++ Header Brings Unified Interface for Different Languages
Install / Use
/learn @zdzhaoyong/SvarREADME
Svar, A Tiny Modern C++ Header Brings Unified Interface for Different Languages
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
<table> <tr> <th>1. Bind C++ to hello.so</th> <th>2. Import by C++</th> <th>3. Import by Python</th> </tr> <tr> <td valign="top"> <pre> #include <Svar.h> void say(std::string v){ std::cerr<<v<<std::endl; } REGISTER_SVAR_MODULE(hello) { svar["say"] = say; } EXPORT_SVAR_INSTANCE </pre></td> <td valign="top"> <pre> #include <Svar.h> auto m=svar.import("hello"); int main(){ m["say"]("hello world"); return 0; } </pre></td> <td valign="top"> <pre> import svar hello = svar.load("hello") hello.say("hello world") </pre></td> <tr> <th>4. Import by Javascript</th> <th>5. C++ import Python</th> <th>6. Javascript import Python</th> </tr> <tr> <td valign="top"> <pre> svar = require('./svar') hello = svar('hello') hello.say("hello world") </pre></td> <td valign="top"> <pre> #include <Svar.h> auto py=svar.import("svarpy"); int main(){ auto os = py["import]("os"); std::cout<<"Pid is:" <<os["getpid"](); return 0; } </pre></td> <td valign="top"> <pre> svar=require("./svar") python=svar("svarpy") os=python.import("os") print("Pid is", os.getpid()) </pre></td> </table>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)
Related Skills
node-connect
352.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
111.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
352.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
352.2kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
