mirror of
https://github.com/sipeed/MaixCDK.git
synced 2026-09-11 06:09:42 -05:00
443 lines
16 KiB
C++
443 lines
16 KiB
C++
/**
|
|
* @file maix_py_example.hpp
|
|
* @brief This is an example of how to export API to MaixPy
|
|
* 1. Create a C++ header file(.hpp) in anywhere of components' include path, like this hpp file.
|
|
* 2. Add C++ API in this hpp file, and API should be in maix namespace. API can be class or function etc. See below examples.
|
|
* 3. Add comments for each API like normal C++ API(doxygen style).
|
|
* !! Be attention, parameter MUST add value range or value attention, and return value the same.
|
|
* !! Only doc with detail meaning and value attention will actually help user to understand and easily use API.
|
|
* e.g. "@param age age of person" is bad, because developer can't know if age have limit or not. So better is:
|
|
* "@param age age of person, value range is [0, 100]".
|
|
* 4. And add @maixpy keyword in comments, this will inform generator to generate MaixPy API, format see below examples.
|
|
* 4. Compile MaixPy project, and then you can use these APIs in MaixPy.
|
|
* @attention MaixPy API code will be automatically generated by `components/maix/gen_api.py` script,
|
|
* to avoid trigger unexpected BUG, please:
|
|
* 1. Define one module in one header file !
|
|
* 2. DO NOT use complex C++ grammar and hierarchy !
|
|
* 3. Only the below grammar was tested !
|
|
* @author neucrack@sipeed
|
|
* @license Apache 2.0
|
|
* @update 2023.9.8: Add framework, create this file.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
#include <valarray>
|
|
#include <functional>
|
|
#include "maix_type.hpp"
|
|
// using namespace std; // !! not recommend, because it will pollute global namespace
|
|
|
|
namespace maix
|
|
{
|
|
|
|
/**
|
|
* example module, this will be maix.example module in MaixPy, maix::example namespace in MaixCDK
|
|
* @maixpy maix.example
|
|
*/
|
|
namespace example
|
|
{
|
|
/**
|
|
* Test class
|
|
* @maixpy maix.example.Test
|
|
*/
|
|
class Test
|
|
{
|
|
public:
|
|
/**
|
|
* Test constructor
|
|
* @maixpy maix.example.Test.__init__
|
|
* @maixcdk maix.example.Test.Test
|
|
*/
|
|
Test()
|
|
{
|
|
data = new int[1024 * 1024];
|
|
printf("Test() new data: %p, size: %d\n", data, 1024 * 1024);
|
|
}
|
|
|
|
~Test()
|
|
{
|
|
printf("~Test() delete data: %p\n", data);
|
|
delete[] (int *)data;
|
|
}
|
|
|
|
private:
|
|
void *data;
|
|
};
|
|
|
|
/**
|
|
* @brief Example enum(not recommend! See Kind2)
|
|
* @maixpy maix.example.Kind
|
|
*/
|
|
enum Kind
|
|
{
|
|
KIND_NONE = 0, /** Kind none, value always 0, other enum value will auto increase */
|
|
KIND_DOG, /** Kind dog*/
|
|
KIND_CAT, // Kind cat, value is auto generated according to KING_DOG
|
|
KIND_BIRD,
|
|
KIND_MAX /* Max Kind quantity,
|
|
You can get max Kind value by KIND_MAX - 1
|
|
*/
|
|
};
|
|
|
|
/**
|
|
* @brief Example enum class(recommend!)
|
|
* @maixpy maix.example.Kind2
|
|
*/
|
|
enum class Kind2
|
|
{
|
|
NONE = 0, /** Kind none, value always 0, other enum value will auto increase */
|
|
DOG, /** Kind dog*/
|
|
CAT, // Kind cat, value is auto generated according to KING_DOG
|
|
BIRD,
|
|
MAX /* Max Kind quantity,
|
|
You can get max Kind value by KIND_MAX - 1
|
|
*/
|
|
};
|
|
|
|
/**
|
|
* @brief Example module variable
|
|
* @attention It's a copy of this variable in MaixPy,
|
|
* so change it in C++ (e.g. update var in hello function) will not take effect the var inMaixPy.
|
|
* So we add const for this var to avoid this mistake.
|
|
* @maixpy maix.example.var1
|
|
*/
|
|
const std::string var1 = "Sipeed";
|
|
|
|
/**
|
|
* Tensor data type size in bytes
|
|
* @attention DO NOT use C/C++ array directly for python API, the python wrapper not support it.
|
|
* Use std::vector instead.
|
|
* @attention It's a copy of this variable in MaixPy,
|
|
* so change it in C++ (e.g. update var in hello function) will not take effect the var inMaixPy.
|
|
* So we add const for this var to avoid this mistake.
|
|
* @maixpy maix.example.list_var
|
|
*/
|
|
const std::vector<int> list_var = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
|
|
|
/**
|
|
* @brief Example module variable test_var
|
|
* @attention It's a copy of this variable in MaixPy, so if you change it in C++, it will not take effect in MaixPy.
|
|
* And change it in MaixPy will not take effect in C++ as well !!!
|
|
* If you want to use vars shared between C++ and MaixPy, you can create a class and use its member.
|
|
* @maixpy maix.example.test_var
|
|
*/
|
|
int test_var = 100;
|
|
|
|
/**
|
|
* @brief say hello to someone
|
|
* @param[in] name name of someone, string type
|
|
* @return string type, content is hello + name
|
|
* @maixpy maix.example.hello
|
|
*/
|
|
std::string hello(std::string name)
|
|
{
|
|
return "hello " + name + ", " + std::to_string(test_var);
|
|
}
|
|
|
|
/**
|
|
* This is an API only for MaixCDK, MaixPy can't use it.
|
|
* Only item with `maixcdk` or `maixpy` keyword will be exported as MaixCDK API.
|
|
* @maixcdk maix.example.hello_maixcdk
|
|
*/
|
|
std::string hello_maixcdk(std::string name)
|
|
{
|
|
return "hello " + name + " from MaixCDK";
|
|
}
|
|
|
|
/**
|
|
* @brief Example class
|
|
* this class will be export to MaixPy as maix.example.Example
|
|
* @maixpy maix.example.Example
|
|
*/
|
|
class Example
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Example constructor
|
|
* this constructor will be export to MaixPy as maix.example.Example.__init__
|
|
* @param[in] name name of Example, string type
|
|
* @param[in] age age of Example, int type, default is 18, value range is [0, 100]
|
|
* @attention to make auto generate code work, param Kind should with full namespace name `example::Kind` instead of `Kind`,
|
|
* namespace `maix` can be ignored.
|
|
* @maixpy maix.example.Example.__init__
|
|
* @maixcdk maix.example.Example.Example
|
|
*/
|
|
Example(std::string &name, int age = 18, example::Kind pet = example::KIND_NONE)
|
|
{
|
|
if (age < 0 || age > 100)
|
|
{
|
|
// throw exception will automatically translate to Python exception in MaixPy
|
|
throw std::invalid_argument("age should be in [0, 100]");
|
|
}
|
|
this->name = name;
|
|
this->age = age;
|
|
this->_pet = pet;
|
|
}
|
|
|
|
~Example()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief get name of Example
|
|
* you can also get name by property `name`.
|
|
* @return name of Example, string type
|
|
* @maixpy maix.example.Example.get_name
|
|
*/
|
|
std::string get_name()
|
|
{
|
|
return this->name;
|
|
}
|
|
|
|
/**
|
|
* @brief get age of Example
|
|
* @return age of Example, int type, value range is [0, 100]
|
|
* @maixpy maix.example.Example.get_age
|
|
*/
|
|
int get_age()
|
|
{
|
|
return this->age;
|
|
}
|
|
|
|
/**
|
|
* @brief set name of Example
|
|
* @param name name of Example, string type
|
|
* @maixpy maix.example.Example.set_name
|
|
*/
|
|
void set_name(std::string name)
|
|
{
|
|
this->name = name;
|
|
}
|
|
|
|
/**
|
|
* @brief set age of Example
|
|
* @param age age of Example, int type, value range is [0, 100]
|
|
* @maixpy maix.example.Example.set_age
|
|
*/
|
|
void set_age(int age)
|
|
{
|
|
this->age = age;
|
|
}
|
|
|
|
/**
|
|
* @brief Example enum member
|
|
* @attention
|
|
* @maixpy maix.example.Example.set_pet
|
|
*/
|
|
void set_pet(example::Kind pet)
|
|
{
|
|
_pet = pet;
|
|
}
|
|
|
|
/**
|
|
* @brief Example enum member
|
|
*
|
|
* @maixpy maix.example.Example.get_pet
|
|
*/
|
|
example::Kind get_pet()
|
|
{
|
|
return _pet;
|
|
}
|
|
|
|
/**
|
|
* get_pet overload function, only can be used in C++.
|
|
* if there are many overload functions, only the one can be export to MaixPy.
|
|
* @param pet pet of Example, enum type, default is KIND_DOG
|
|
*/
|
|
example::Kind get_pet(example::Kind pet)
|
|
{
|
|
if (_pet == example::KIND_NONE)
|
|
_pet = pet;
|
|
return _pet;
|
|
}
|
|
|
|
/**
|
|
* @brief get list example
|
|
* @param[in] in input list, items are int type.
|
|
* In MaixPy, you can pass list or tuple to this API
|
|
* @return list, items are int type, content is [1, 2, 3] + in. Alloc item, del in MaixPy will auto free memory.
|
|
* @maixpy maix.example.Example.get_list
|
|
*/
|
|
std::vector<int> *get_list(std::vector<int> in)
|
|
{
|
|
std::vector<int> *final = new std::vector<int>;
|
|
final->push_back(1);
|
|
final->push_back(2);
|
|
final->push_back(3);
|
|
for (auto i : in)
|
|
{
|
|
final->push_back(i);
|
|
}
|
|
return final;
|
|
}
|
|
|
|
/**
|
|
* @brief Example dict API
|
|
* @param[in] in input dict, key is string type, value is int type.
|
|
* In MaixPy, you can pass `dict` to this API
|
|
* @return dict, key is string type, value is int type, content is {"a": 1} + in
|
|
* In MaixPy, return type is `dict` object
|
|
* @maixpy maix.example.Example.get_dict
|
|
*/
|
|
std::map<std::string, int> get_dict(std::map<std::string, int> &in)
|
|
{
|
|
std::map<std::string, int> final = {{"a", 1}};
|
|
for (auto i : in)
|
|
{
|
|
final[i.first] = i.second;
|
|
}
|
|
return final;
|
|
}
|
|
|
|
/**
|
|
* @brief say hello to someone
|
|
* @param name name of someone, string type
|
|
* @return string type, content is Example::hello_str + name
|
|
* @maixpy maix.example.Example.hello
|
|
*/
|
|
static std::string hello(std::string name)
|
|
{
|
|
return Example::hello_str + name;
|
|
}
|
|
|
|
/**
|
|
* @brief param is bytes example
|
|
* @param bytes bytes type param
|
|
* @return bytes type, return value is bytes changed value
|
|
* @maixpy maix.example.Example.hello_bytes
|
|
*/
|
|
static Bytes *hello_bytes(Bytes &bytes)
|
|
{
|
|
printf("hello_bytes: %ld\n", bytes.size());
|
|
for (auto i : bytes)
|
|
{
|
|
printf("%02x ", i);
|
|
}
|
|
printf("\n");
|
|
|
|
// change bytes will not affect the original bytes in MaixPy
|
|
bytes.data[0] = 0x11;
|
|
bytes.data[1] = 0x22;
|
|
return new Bytes(bytes.data, bytes.size(), true, true);
|
|
}
|
|
|
|
/**
|
|
* Callback example
|
|
* @param cb callback function, param is two int type, return is int type
|
|
* @return int type, return value is cb's return value.
|
|
* @maixpy maix.example.Example.callback
|
|
*/
|
|
static int callback(std::function<int(int, int)> cb)
|
|
{
|
|
return cb(1, 2);
|
|
}
|
|
|
|
/**
|
|
* Callback example
|
|
* @param cb callback function, param is a int list type and int type, return is int type
|
|
* @return int type, return value is cb's return value.
|
|
* @maixpy maix.example.Example.callback2
|
|
*/
|
|
static int callback2(std::function<int(std::vector<int>, int)> cb)
|
|
{
|
|
std::vector<int> a;
|
|
a.push_back(1);
|
|
return cb(a, 2);
|
|
}
|
|
|
|
/**
|
|
* Dict param example
|
|
* @param dict dict type param, key is string type, value is int type
|
|
* @maixpy maix.example.Example.hello_dict
|
|
*/
|
|
static std::map<std::string, int> *hello_dict(std::map<std::string, int> *dict)
|
|
{
|
|
printf("hello_dict: %ld\n", dict->size());
|
|
for (auto i : *dict)
|
|
{
|
|
printf("%s: %d\n", i.first.c_str(), i.second);
|
|
}
|
|
// change dict value will not affect the original dict in MaixPy
|
|
(*dict)["a"] = 100;
|
|
return dict;
|
|
}
|
|
|
|
/**
|
|
* @brief name member of Example
|
|
* @maixpy maix.example.Example.name
|
|
*/
|
|
std::string name;
|
|
|
|
/**
|
|
* @brief age member of Example, value range should be [0, 100]
|
|
* @maixpy maix.example.Example.age
|
|
*/
|
|
int age;
|
|
|
|
/**
|
|
* @brief hello_str member of Example, default value is "hello "
|
|
* @maixpy maix.example.Example.hello_str
|
|
*/
|
|
static std::string hello_str;
|
|
|
|
/**
|
|
* @brief Example module readonly variable
|
|
* @maixpy maix.example.Example.var1
|
|
*/
|
|
const std::string var1 = "Example.var1";
|
|
|
|
/**
|
|
* @brief Example module readonly variable
|
|
* @maixpy maix.example.Example.var2
|
|
* :readonly
|
|
*/
|
|
std::string var2 = "Example.var2";
|
|
|
|
/**
|
|
* dict_test, return dict type, and element is pointer type(alloc in C++).
|
|
* Here when the returned Tensor object will auto delete by Python GC.
|
|
* @maixpy maix.example.Example.dict_test
|
|
*/
|
|
static std::map<std::string, example::Test *> *dict_test()
|
|
{
|
|
std::map<std::string, example::Test *> *dict = new std::map<std::string, example::Test *>;
|
|
(*dict)["a"] = new Test();
|
|
return dict;
|
|
}
|
|
|
|
private:
|
|
Kind _pet;
|
|
};
|
|
|
|
std::string Example::hello_str = "hello ";
|
|
|
|
/**
|
|
* Change arg name example
|
|
* @param e Example object
|
|
* @return same as arg
|
|
* @maixpy maix.example.change_arg_name
|
|
*/
|
|
example::Example *change_arg_name(example::Example *e)
|
|
{
|
|
e->name = "changed_name";
|
|
return e;
|
|
}
|
|
|
|
/**
|
|
* Change arg name example
|
|
* @param e Example object
|
|
* @maixpy maix.example.change_arg_name2
|
|
*/
|
|
void change_arg_name2(example::Example &e)
|
|
{
|
|
e.name = "changed_name2";
|
|
}
|
|
|
|
} // namespace example
|
|
} // namespace maix
|