【开发日志】2022.08.22 支持ZENO把primitive对象导出为csv文件【参考结点 ParamFormat 、ParamFileParser】

本文主要是介绍【开发日志】2022.08.22 支持ZENO把primitive对象导出为csv文件【参考结点 ParamFormat 、ParamFileParser】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

任务:支持把primitive对象导出为csv文件,方便用户在excel里打开查看

预备知识

CSV

671e786ae787400d8daffb81a1f789ca.png

 06937f4acc0849b3aa7ef8c939215f7b.png

9d22a63ce2db41c0a5902729d6394381.png

读取CSV 

#include <iostream>
#include <fstream>
#include <vector>
#include <string>using namespace std;vector<vector<string>> readCSV(string path) {vector<vector<string>> data;// 打开CSV文件ifstream file(path);if (!file.is_open()) {cout << "无法打开文件:" << path << endl;return data;}// 逐行读取文件内容string line;while (getline(file, line)) {vector<string> row;string field;// 将每一行按照逗号分隔符进行分割,并存储到vector中for (char c : line) {if (c == ',') {row.push_back(field);field.clear();} else {field += c;}}row.push_back(field);data.push_back(row);}// 关闭文件file.close();return data;
}int main() {string path = "data.csv";vector<vector<string>> data = readCSV(path);for (auto& row : data) {for (auto& field : row) {cout << field << ",";}cout << endl;}return 0;
}

导出csv

#include <iostream>
#include <fstream>
#include <vector>
#include <string>using namespace std;void writeCSV(string path, vector<vector<string>> data) {// 创建CSV文件并打开文件ofstream file(path);if (!file.is_open()) {cout << "无法创建文件:" << path << endl;return;}// 将vector中的数据写入CSV文件中for (auto& row : data) {for (auto& field : row) {file << field << ",";}file << endl;}// 关闭文件file.close();
}int main() {string path = "data.csv";vector<vector<string>> data = {{"id", "name", "age"},{"1", "张三", "20"},{"2", "李四", "21"},{"3", "王五", "22"}};writeCSV(path, data);cout << "CSV文件已成功导出到:" << path << endl;return 0;
}

C++字符串转换(stoi;stol;stoul;stoll;stoull;stof;stod;stold)

\Yongqiang Cheng的博客-CSDN博客_std::stoi

C++字符串转换(stoi;stol;stoul;stoll;stoull;stof;stod;stold)_WilliamX2020的博客-CSDN博客_stoul

void testTypeConvert()
{//int --> stringint i = 5;string s = to_string(i);cout << s << endl;//double --> stringdouble d = 3.14;cout << to_string(d) << endl;//long --> stringlong l = 123234567;cout << to_string(l) << endl;//char --> stringchar c = 'a';cout << to_string(c) << endl;	//自动转换成int类型的参数//char --> stringstring cStr; cStr += c;cout << cStr << endl;s = "123.257";//string --> int;cout << stoi(s) << endl;//string --> intcout << stol(s) << endl;//string --> floatcout << stof(s) << endl;//string --> doubelcout << stod(s) << endl;
}

output:

53.14000012323456797a123123123.257123.257

std::varient

从C中采用的c++提供了对union的支持,union是能够保存可能类型列表之一的对象。但是,这种语言特性也有一些缺点:

对象不知道它们当前持有的值的类型。
由于这个原因,您不能有non-trivial的成员,比如std::string(从c++ 11起, union原则上可以有non-trivial的成员,但是必须实现特殊的成员函数,比如复制构造函数和析构函数,因为只有通过代码逻辑才能知道哪个成员是可用的。)
不能从union中派生类。
     对于std:: variable <>, c++标准库提供了一个封闭的区分联合(这意味着有一个指定的可能类型列表,可以指定你要指的是哪种类型),其中:

当前值的类型总是已知的;
可以有任何指定类型的成员;
可以派生类。
事实上,一个std:: variable <>拥有不同的替代值,这些替代值通常具有不同的类型。与std::optional<>和std::any一样,生成的任何对象都具有值语义。也就是说,通过在它自己的内存中创建一个具有当前替代的当前值的独立对象来进行深度复制。因此,复制std:: variable <>与复制当前替代的类型/值一样便宜/昂贵。支持Move语义。

std:: variable <>的核心功能:

#include <variant>std::variant<int, std::string> var{"hi"}; // initialized with string alternative
std::cout << var.index(); // prints 1
var = 42; // now holds int alternative
std::cout << var.index(); // prints 0
...
try {
std::string s = std::get<std::string>(var); // access by type
int i = std::get<0>(var); // access by index
}
catch (const std::bad_variant_access& e) { // in case a wrong type/index is used
...
}

 成员函数index()可用于查明当前设置了哪个选项(第一个选项的索引为0)。初始化和赋值总是使用最佳匹配来找到新选项。如果类型不完全匹配,可能会出现意外。

    注意,不允许使用空变量、具有引用成员的变量、具有c样式数组成员的变量和具有不完整类型(如void)的变量。没有空的状态:这意味着对于每个构建的对象,必须至少调用一个构造函数。默认构造函数初始化第一个类型(通过第一个类型的默认构造函数):

std::variant<std::string, int> var; // => var.index() == 0, value == ””

如果没有为第一个类型定义默认构造函数,则调用该变量的默认构造函数会在编译时错误

不过辅助类型std::monostate提供了处理这种情况的能力,还提供了模拟空状态的能力。

std::monostate


为了支持第一个类型没有默认构造函数的variant对象,提供了一个特殊的helper类型:std::monostate。类型std::monostate的对象总是具有相同的状态,因此,它们总是相等的。它自己的目的是表示另一种类型,这样variant就没有任何其他类型的值。也就是说,std::monostate可以作为第一种替代类型,使变体类型默认为可构造的。例如:

std::variant<std::monostate, NoDefConstr> v2; // OK
std::cout << "index: " << v2.index() << '\n'; // prints 0

在某种程度上,你可以把这种状态解释为模拟的(原则上,std::monostate可以作为任何替代,而不仅仅是第一个替代,当然,这个替代不能帮助使变体的默认构造成为可构造的)。

有多种方法可以检查monostate,这也演示了一些其他的操作,你可以调用变量:

#include <iostream>
#include <variant>struct NoDefConstr
{NoDefConstr(int i){std::cout << "NoDefConstr::NoDefConstr(int) called\n";}
};int main()
{std::variant<std::monostate, NoDefConstr> v2; // OKstd::cout << "index: " << v2.index() << '\n'; // prints 0if (v2.index() == 0) {std::cout << "has monostate\n";}if (!v2.index()) {std::cout << "has monostate\n";}if (std::holds_alternative<std::monostate>(v2)) {std::cout << "has monostate\n";}if (std::get_if<0>(&v2)) {std::cout << "has monostate\n";}if (std::get_if<std::monostate>(&v2)) {std::cout << "has monostate\n";}return 0;
}

output:

20190911205326862.png

get_if < T>()使用一个指向一个variant的指针,如果当前的选项是T,返回一个指向当前选项的指针,否则它将返回nullptr。这与get<T>()不同,get<T>()接受对变量的引用,如果提供的类型正确,则按值返回当前替代,否则抛出异常。和往常一样,您可以为另一个选项赋值,甚至可以为monostate赋值,再次表示为空:
 

v2 = 42;
std::cout << "index: " << v2.index() << '\n'; // index: 1v2 = std::monostate{};
std::cout << "index: " << v2.index() << '\n'; // index: 0

variant的派生类

可以从std::variant派生出子类。例如,可以定义一个从std:: variable <>派生的聚合,如下所示:

include <iostream>
#include <variant>class Derived : public std::variant<int, std::string> 
{
};int main()
{Derived d = { {"hello"} };std::cout << d.index() << '\n'; // prints: 1std::cout << std::get<1>(d) << '\n'; // prints: hellod.emplace<0>(77); // initializes int, destroys stringstd::cout << d.index() << '\n'; // prints: 0std::cout << std::get<0>(d) << '\n'; // prints: 77return 0;
}

output:

20190911210448603.png

std::variant<>的类型

在头文件< variable >中,c++标准库定义了类std:: variable <>,如下所示:

namespace std 
{template<typename Types...> class variant;
}

也就是说,std:: variable <>是一个可变参数类模板(c++ 11引入的一个特性,允许处理任意数量的类型)。

此外,定义了以下类型和对象:

类型 std::variant_size   
类型 std::variant_alternative 
值 std::variant_npos   
类型 std::monostate
异常类std::bad_variant_access派生自std:: Exception。

std::variant操作

如下列出了为std:: variable <>提供的所有操作。

232d00d344ab4c29ae3ab9cf683b068b.png

1. 构造函数

默认情况下,变量的默认构造函数调用第一个备选项的默认构造函数:

std::variant<int, int, std::string> v1; // sets first int to 0, index()==0

另一种方法是初始化值,这意味着对于基本类型,它是0、false还是nullptr。如果传递一个值进行初始化,则使用最佳匹配类型: 

std::variant<long, int> v2{42};
std::cout << v2.index() << '\n'; // prints 1

然而,如果两种类型匹配得同样,则调用是不明确的:

std::variant<long, long> v3{42}; // ERROR: ambiguous
std::variant<int, float> v4{42.3}; // ERROR: ambiguous
std::variant<int, double> v5{42.3}; // OK
std::variant<std::string, std::string_view> v6{"hello"}; // ERROR: ambiguous
std::variant<std::string, std::string_view, const char*> v7{"hello"}; // OK
std::cout << v7.index() << '\n'; // prints 2

要传递多个值进行初始化,必须使用in_place_type或in_place_index标记:

std::variant<std::complex<double>> v8{3.0, 4.0}; // ERROR
std::variant<std::complex<double>> v9{{3.0, 4.0}}; // ERROR
std::variant<std::complex<double>> v10{std::in_place_type<std::complex<double>>,
3.0, 4.0};
std::variant<std::complex<double>> v11{std::in_place_index<0>, 3.0, 4.0};

当然,可以使用in_place_index标签来解决初始化过程中的歧义或匹配问题:

std::variant<int, int> v12{std::in_place_index<1>, 77}; // init 2nd int
std::variant<int, long> v13{std::in_place_index<1>, 77}; // init long, not int
std::cout << v13.index() << '\n'; // prints 1

甚至可以传递一个初始化器列表,后面跟着附加的参数:

// initialize variant with a set with lambda as sorting criterion:
auto sc = [] (int x, int y) 
{return std::abs(x) < std::abs(y);
};std::variant<std::vector<int>,std::set<int,decltype(sc)>> v14{std::in_place_index<1>, {4, 8, -7, -2, 0, 5}, sc};

不能对std:: variable <>使用类模板参数推导,而且不存在make_variable <>()便利函数(与std::optional<>和std::any不同)。两者都没有意义,因为变体的整个目标是处理多个替代方案。

访问值

访问值的通常方法是调用get<>()获取对应的选项值。可以传递它的索引或者类型。例如:

std::variant<int, int, std::string> var; // sets first int to 0, index()==0
auto a = std::get<double>(var); // compile-time ERROR: no double
auto b = std::get<4>(var); // compile-time ERROR: no 4th alternative
auto c = std::get<int>(var); // compile-time ERROR: int twicetry{auto s = std::get<std::string>(var); // throws exception (first int currently set)auto i = std::get<0>(var); // OK, i==0auto j = std::get<1>(var); // throws exception (other int currently set)
}
catch (const std::bad_variant_access& e) { // in case of an invalid accessstd::cout << "Exception: " << e.what() << '\n';
}

也有一个API来访问该值的选项,检查它是否存在:

if (auto ip = std::get_if<1>(&var); ip) 
{std::cout << *ip << '\n';
}
else
{std::cout << "alternative with index 1 not set\n";
}

必须将variant变量的指针传递给get_if<>(),它要么返回指向当前值的指针,要么返回nullptr。注意,这里使用了if with initialize,它允许检查刚刚初始化的值。另一种访问不同选项值的方法是variant访问器(后续文章会介绍)。

修改值


赋值和emplace()操作对应于初始化:

std::variant<int, int, std::string> var; // sets first int to 0, index()==0
var = "hello"; // sets string, index()==2
var.emplace<1>(42); // sets second int, index()==1

还可以使用get<>()或get_if<>()来为当前选项值分配一个新值:

std::variant<int, int, std::string> var; // sets first int to 0, index()==0
std::get<0>(var) = 77; // OK, because first int already set
std::get<1>(var) = 99; // throws exception (other int currently set)if (auto p = std::get_if<1>(&var); p) { // if second int set
*p = 42; // modify it
}

修改不同备选项值的另一种方法是使用不同的访问者。

4. variant对象比较
对于两个类型相同的variant(相同的备选项和顺序),可以使用通常的比较运算符。运算符根据如下规则:

对于都有值的两个variant对象,index小的对象大于index大的对象;
对于两个都有值并且index也相等的两个variant对象,按照其相应类型的比较运算符比较。注意所有对象的std::monostate对象总是相等的;
例4:

#include <iostream>
#include <variant>int main()
{std::variant<std::monostate, int, std::string, float> v1, v2{ "hello" }, v3{ 42 };std::variant<std::monostate, std::string, int> v4;//v1 == v4 // COMPILE-TIME ERRORstd::cout << std::boolalpha;std::cout << (v1 == v2) << std::endl;// yields falsestd::cout << (v1 < v2) << std::endl; // yields truestd::cout << (v1 < v3) << std::endl; // yields truestd::cout << (v2 < v3) << std::endl; // yields falsestd::cout << (v2 == v3) << std::endl; // yields falsestd::cout << (v2 > v3) << std::endl; // yields truev1 = "hello";std::cout << (v1 == v2) << std::endl;// yields truev2 = 41;std::cout << (v2 < v3) << std::endl; // yields truestd::cout << std::noboolalpha;return 0;
}

参考结点

ParamFormat 、ParamFileParser

21d5407ea9aa5a1af15f1e01b647a548.png

InputParams.cpp

#include <zeno/zeno.h>
#include <zeno/types/DictObject.h>
#include <zeno/types/NumericObject.h>
#include <filesystem>
#include "zeno/utils/log.h"
#include "zeno/types/ListObject.h"
#include "zeno/utils/string.h"
#include <cstdio>
#include <fstream>
#include <set>namespace zeno {
namespace {using DefaultValue = std::variant<int,vec2i,vec3i,vec4i,float,vec2f,vec3f,vec4f,std::string>;struct ParamFormatInfo: IObject {std::string name;std::string _type;DefaultValue defaultValue;
};struct ParamFormat : zeno::INode {virtual void apply() override {auto format = std::make_shared<zeno::ParamFormatInfo>();format->name = get_input2<std::string>("name");format->_type = get_input2<std::string>("type");auto defaultValue = get_input2<std::string>("defaultValue");auto items = zeno::split_str(defaultValue, ',');if (format->_type == "int") {format->defaultValue = std::stoi(defaultValue);}else if (format->_type == "vec2i") {format->defaultValue = vec2i(std::stoi(items[0]),std::stoi(items[1]));}else if (format->_type == "vec3i") {format->defaultValue = vec3i(std::stoi(items[0]),std::stoi(items[1]),std::stoi(items[2]));}else if (format->_type == "vec4i") {format->defaultValue = vec4i(std::stoi(items[0]),std::stoi(items[1]),std::stoi(items[2]),std::stoi(items[3]));}else if (format->_type == "float") {format->defaultValue = std::stof(defaultValue);}else if (format->_type == "vec2f") {format->defaultValue = vec2f(std::stof(items[0]),std::stof(items[1]));}else if (format->_type == "vec3f") {format->defaultValue = vec3f(std::stof(items[0]),std::stof(items[1]),std::stof(items[2]));}else if (format->_type == "vec4f") {format->defaultValue = vec4f(std::stof(items[0]),std::stof(items[1]),std::stof(items[2]),std::stof(items[3]));}else {format->defaultValue = defaultValue;}set_output("format", std::move(format));}
};ZENDEFNODE(ParamFormat, {{{"string", "name"},{"enum float vec2f vec3f vec4f int vec2i vec3i vec4i string", "type", "string"},{"string", "defaultValue"},},{"format"},{},{"string"},
});struct ParamFileParser : zeno::INode {virtual void apply() override {auto formatList = get_input<zeno::ListObject>("formatList");auto params = std::make_shared<zeno::DictObject>();auto path = get_input2<std::string>("configFilePath");std::set<std::string> saved_names;if (std::filesystem::exists(path)) {auto is = std::ifstream(path);while (!is.eof()) {std::string line;std::getline(is, line);line = zeno::trim_string(line);if (line.empty()) {continue;}auto items = zeno::split_str(line, ',');zany value;if (items[1] == "int") {value = std::make_shared<NumericObject>(std::stoi(items[2]));}else if (items[1] == "vec2i") {value = std::make_shared<NumericObject>(vec2i(std::stoi(items[2]),std::stoi(items[3])));}else if (items[1] == "vec3i") {value = std::make_shared<NumericObject>(vec3i(std::stoi(items[2]),std::stoi(items[3]),std::stoi(items[4])));}else if (items[1] == "vec4i") {value = std::make_shared<NumericObject>(vec4i(std::stoi(items[2]),std::stoi(items[3]),std::stoi(items[4]),std::stoi(items[5])));}else if (items[1] == "float") {value = std::make_shared<NumericObject>(std::stof(items[2]));}else if (items[1] == "vec2f") {value = std::make_shared<NumericObject>(vec2f(std::stof(items[2]),std::stof(items[3])));}else if (items[1] == "vec3f") {value = std::make_shared<NumericObject>(vec3f(std::stof(items[2]),std::stof(items[3]),std::stof(items[4])));}else if (items[1] == "vec4f") {value = std::make_shared<NumericObject>(vec4f(std::stof(items[2]),std::stof(items[3]),std::stof(items[4]),std::stof(items[5])));}else {value = std::make_shared<StringObject>(items[2]);}params->lut[items[0]] = value;saved_names.insert(items[0]);}is.close();}{FILE *fp = fopen(path.c_str(), "a");if (!fp) {perror(path.c_str());abort();}for (auto &ptr: formatList->arr) {auto p = std::static_pointer_cast<ParamFormatInfo>(ptr);if (saved_names.count(p->name)) {continue;}zany value;if (std::holds_alternative<int>(p->defaultValue)) {auto v = std::get<int>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%d\n", p->name.c_str(), p->_type.c_str(), v);}else if (std::holds_alternative<vec2i>(p->defaultValue)) {auto v = std::get<vec2i>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%d,%d\n", p->name.c_str(), p->_type.c_str(), v[0], v[1]);}else if (std::holds_alternative<vec3i>(p->defaultValue)) {auto v = std::get<vec3i>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%d,%d,%d\n", p->name.c_str(), p->_type.c_str(), v[0], v[1], v[2]);}else if (std::holds_alternative<vec4i>(p->defaultValue)) {auto v = std::get<vec4i>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%d,%d,%d,%d\n", p->name.c_str(), p->_type.c_str(), v[0], v[1], v[2], v[3]);}else if (std::holds_alternative<float>(p->defaultValue)) {auto v = std::get<float>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%f\n", p->name.c_str(), p->_type.c_str(), v);}else if (std::holds_alternative<vec2f>(p->defaultValue)) {auto v = std::get<vec2f>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%f,%f\n", p->name.c_str(), p->_type.c_str(), v[0], v[1]);}else if (std::holds_alternative<vec3f>(p->defaultValue)) {auto v = std::get<vec3f>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%f,%f,%f\n", p->name.c_str(), p->_type.c_str(), v[0], v[1], v[2]);}else if (std::holds_alternative<vec4f>(p->defaultValue)) {auto v = std::get<vec4f>(p->defaultValue);value = std::make_shared<NumericObject>(v);fprintf(fp, "%s,%s,%f,%f,%f,%f\n", p->name.c_str(), p->_type.c_str(), v[0], v[1], v[2], v[3]);}else if (std::holds_alternative<std::string>(p->defaultValue)) {auto v = std::get<std::string>(p->defaultValue);value = std::make_shared<StringObject>(v);fprintf(fp, "%s,%s,%s\n", p->name.c_str(), p->_type.c_str(), v.c_str());}params->lut[p->name] = value;}fclose(fp);}set_output("params", std::move(params));}
};ZENDEFNODE(ParamFileParser, {{"formatList",{"writepath", "configFilePath"},},{{"DictObject", "params"},},{},{"string"},
});}
}

PrimCSVIO.cpp

#include <zeno/zeno.h>
#include <zeno/types/PrimitiveObject.h>
#include <zeno/funcs/PrimitiveUtils.h>
#include <zeno/types/StringObject.h>
#include <zeno/utils/variantswitch.h>
#include <zeno/utils/arrayindex.h>
#include <zeno/utils/string.h>
#include <zeno/utils/log.h>
#include <zeno/utils/vec.h>
#include <fstream>namespace zeno {
namespace {static void dump(int const &v, std::ostream &fout) {fout << v;
}static void dump(float const &v, std::ostream &fout) {fout << v;
}template <size_t N, class T>
static void dump(vec<N, T> const &v, std::ostream &fout) {fout << v[0];for (int i = 1; i < N; i++)fout << ' ' << v[i];
}template <class T>
void dump_csv(AttrVector<T> avec, std::ostream &fout) {fout << "pos";avec.template foreach_attr<AttrAcceptAll>([&] (auto const &key, auto &arr) {fout << ',' << key;});fout << '\n';for (int i = 0; i < avec.size(); i++) {dump(avec[i], fout);avec.template foreach_attr<AttrAcceptAll>([&] (auto const &key, auto &arr) {fout << ',';dump(arr[i], fout);});fout << '\n';}
}struct WritePrimToCSV : INode {virtual void apply() override {auto prim = get_input<PrimitiveObject>("prim");auto path = get_input<StringObject>("path")->get();std::ofstream fout(path);auto mbr = funcalt_variant(array_index({"verts", "points", "lines", "tris", "quads", "loops", "polys"},get_input2<std::string>("type")),&PrimitiveObject::verts,&PrimitiveObject::points,&PrimitiveObject::lines,&PrimitiveObject::tris,&PrimitiveObject::quads,&PrimitiveObject::loops,&PrimitiveObject::polys);std::visit([&] (auto const &mbr) {dump_csv(mbr(*prim), fout);}, mbr);set_output("prim", std::move(prim));}
};ZENDEFNODE(WritePrimToCSV,{ /* inputs: */ {{"primitive", "prim"},{"writepath", "path"},{"enum verts points lines tris quads loops polys", "type", "verts"},}, /* outputs: */ {{"primitive", "prim"},}, /* params: */ {}, /* category: */ {"primitive",}});}
}

这篇关于【开发日志】2022.08.22 支持ZENO把primitive对象导出为csv文件【参考结点 ParamFormat 、ParamFileParser】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799423

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

v0.dev快速开发

探索v0.dev:次世代开发者之利器 今之技艺日新月异,开发者之工具亦随之进步不辍。v0.dev者,新兴之开发者利器也,迅速引起众多开发者之瞩目。本文将引汝探究v0.dev之基本功能与优势,助汝速速上手,提升开发之效率。 何谓v0.dev? v0.dev者,现代化之开发者工具也,旨在简化并加速软件开发之过程。其集多种功能于一体,助开发者高效编写、测试及部署代码。无论汝为前端开发者、后端开发者

pico2 开发环境搭建-基于ubuntu

pico2 开发环境搭建-基于ubuntu 安装编译工具链下载sdk 和example编译example 安装编译工具链 sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib 注意cmake的版本,需要在3.17 以上 下载sdk 和ex