gpt4 book ai didi

C++ 自动将类成员暴露给多个 API

转载 作者:行者123 更新时间:2023-12-01 13:48:03 25 4
gpt4 key购买 nike

短的:
有许多聪明的库可以让你为各种目的公开一个类的成员,比如序列化、暴露在 lua 环境中等。问题是,对于每个聪明的解决方案,你必须为每个人注册一个类的东西api,这会导致大量的工作重复和样板。

有什么方法可以一次性注册一个类及其成员和方法,并附加某种标志并获得各种自动生成的方法

长:
假设我有一个类:

class C {
public:
int i; // Some int
vec3 v; // Some non-POD value
int function(int foo, char bar) // Some function
int hidden; // Some internal stuff I don't want exposed
}

我想要做的是能够在声明时标记各种成员和方法,让它们自动放入各种样板:

所以声明可能看起来像:
class C {
public:
LUAREG JSON BINSER int i; // Marks member "i" to be exposed to the lua enviroment,
// JSON serialisable, binary serialisable
JSON vec3 v; // Only exposed to JSON function

LUAREG void someFunction() {} // Marks this method to be exposed to the lua enviroment
}

或者编写一个注册函数来完成所有声明:
void C::register_class() {
registrator::register_class<C>("C")
.addData("i", &i, FLAG_LUA | FLAG_JSON | FLAG_BINARY_SERIALISABLE)
.addFunction("someFunction", &someFunction, FLAG_LUA)
.end_class()
}

(我曾多次看到这种模式 - 这有名字吗?)
我希望能够为所述类自动生成各种样板函数。例如:
/// Adds all fields with FLAG_JSON to a "json" object to be later serialised
void toJson(const C & c, json & j) {
toJson(c.i, "i", j);
toJson(c.v, "v", j);
}

/// Binary seralises all members with flag FLAG_BINARY_SERIALISABLE and stores the result in s
void serialise(const C & c, string & s) {
serialise(c.i, s);
serialise(c.v, s);
}

/// Registers all stuff with flag FLAG_LUA to some lua environment
void register_lua(lua_State * const L) {
luaReg_FetchContext(L)::addClass("C")
.addData("x", &C::x).comment("Some int") // generates documentation of "int x : Some int"
.addData("v", &C::v).comment("Some vector")
.addFunction("function", &C::function).comment("some function") // generates: "int function(int, char) : some function"
.endClass()
}

/// Register to some *other* lua environment (such as a read only context for rendering)
void register_lua_readonly(lua_State * const L2) {
luaReg_FetchContext(L)::addClass("C")
.addData("x", &C::x, false).comment("Some int")
.endClass()
}

/// Generates some user readable breakdown of all members
string dump() {
...
}

现在你可以看到很多类这将变得非常乏味、臃肿和容易出错,手动执行

解决这个问题的最佳方法是什么?我很想使用宏来吐出函数,但不知道如何接近注册阶段。干杯!

最佳答案

我有一个解决方案 - 我推出了自己的反射库 - https://github.com/SnapperTT/STTR

class C {
public:
int i;
double d;
int func(int z) const {
return z;
}

static int static_var;
static int static_func() { return 5; }
};
int C::static_var = 7;

struct D : public C {
int di;
};

int main(int argc, char ** argv) {
// Registration
sttr::RegNamespace mNamespace("testns");
mNamespace.beginClass<C>("C")
.regField(&C::i, "i")
.regField(&C::d, "d")
.setUserFlags(0x00F00BAA) // Sets the user flags for the last added item
.setUserString("You can use this for whatever")
.setUserData((void *) &someStruct)
.regField(&C::func, "func")

.regField(&C::static_var, "static_var")
.regField(&C::static_func, "static_func")
.endClass()
.findClass("C").beginClass<D>("D") // Class inherritance. Also you can just beginClass<D>("D") inside C
.regField(&D::di, "di")
.endClass();
}

这个解决方案的关键是我可以为注册成员附加标志(所以 LUA 可以是 1 << 0 ,JSON 可以是 1 << 1 等。

自动 json 序列化和 lua 注册是通过访问者完成的。访问者检查成员是否具有相关标志并执行其操作或跳到下一个成员。

我也尝试过使用 RTTR: https://github.com/rttrorg/rttr - 这是一个不错的库,尽管它很笨重。我推出了自己的库,因为我不喜欢访问者界面和大量模板错误消息。

最后,自动记录是通过运行一个脚本来完成的,该脚本执行一堆正则表达式查找和替换以挑选出 typename Foo; /// Some documentation 的案例。并创建一个 static const char * const docv_Foo = "Some documentation";并注册它。这确实为编译添加了一个中间步骤,但它一点也不坏。

关于C++ 自动将类成员暴露给多个 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58832211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com