我使用的是Z3的C API。我已经检查了这些示例,Z3_mk_config()和Z3_mk_context(Z3_config c)用于创建上下文,例如,
Z3_config cfg;
Z3_context ctx;
cfg = Z3_mk_config();
Z3_set_param_value(cfg, "model", "true");
//...
ctx = Z3_mk_context(cfg);
但是,文档说所有这些功能都已弃用,但不要提及现在应该使用哪些功能。
有谁知道现在应该使用哪些函数来创建配置和上下文?
非常感谢任何帮助。谢谢!
答案 0 :(得分:0)
TLDR:
Z3_mk_config
创建一个Z3_config
。 Z3_global_param_set
全局设置配置。Z3_set_param_value
设置特定于上下文的配置。Z3_config
做一个Z3_mk_config
,Z3_del_config
将其删除。SergeyLebedev的评论可能引用了doc
中的这一评论。在Z3的早期版本中,
Z3_config
用于存储全局和 模块配置。现在,我们应该使用Z3_global_param_set
。
过去几天,我正在查看源仓库。在示例文件test_capi.c
中,他们经常使用此mk_context
函数,该函数在与
Z3_context mk_context()
{
Z3_config cfg;
Z3_context ctx;
cfg = Z3_mk_config();
ctx = mk_context_custom(cfg, error_handler);
Z3_del_config(cfg);
return ctx;
}
其中mk_context_custom
与
Z3_context mk_context_custom(Z3_config cfg, Z3_error_handler err)
{
Z3_context ctx;
Z3_set_param_value(cfg, "model", "true");
ctx = Z3_mk_context(cfg);
Z3_set_error_handler(ctx, err);
return ctx;
}
所以看起来Z3_mk_config
和Z3_set_param_value
仍在使用。
医生说Z3_config
和Z3_context
之类的东西应该是“不透明的指针”。但是,将其追到源头时,似乎Z3_config
被声明为没有特定内容的结构,但似乎无论在何处使用,都将其强制转换为明确定义为类的context_params
。
Z3_config
的类型z3_api_h
用
DEFINE_TYPE(Z3_config);
其中DEFINE_TYPE(T)
是在z3_macros.h
中定义的宏,并扩展为typedef struct _ ## T *T
。因此,实际上Z3_config
仅在原型上声明为结构。
函数Z3_mk_config
是Z3_config
的构造函数,是在z3_api.h
中用
Z3_config Z3_API Z3_mk_config(void);
,在api_config_params.cpp
中定义为
Z3_config Z3_API Z3_mk_config(void) {
try {
memory::initialize(UINT_MAX);
LOG_Z3_mk_config();
Z3_config r = reinterpret_cast<Z3_config>(alloc(context_params));
RETURN_Z3(r);
} catch (z3_exception & ex) {
// The error handler is only available for contexts
// Just throw a warning.
warning_msg("%s", ex.msg());
return nullptr;
}
}
在extern "C"
块中。请注意,Z3_API
是也在z3_macros.h
中定义以设置__attribute__ ((visibility ("default")))
的宏,而alloc
是memory_manager.h
中具有#define alloc(T,...) new (memory::allocate(sizeof(T))) T(__VA_ARGS__)
和{{ 1}}是在文件RETURN_Z3
和update_api.py
生成的某些文件中定义的宏。
看来,当创建#define RETURN_Z3(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); } return Z3RES
时,会分配Z3_config
大小的存储块并将其强制转换为context_params
,实际上Z3_config
context_params
中明确定义的类。我忽略了内容,因为它现在不相关。
context_params.h
接下来,class context_params {
....
};
在Z3_set_param_value
中用
api_config_params.cpp
因此,在像普通对象一样使用该函数之前,该函数首先将void Z3_API Z3_set_param_value(Z3_config c, char const * param_id, char const * param_value) {
LOG_Z3_set_param_value(c, param_id, param_value);
try {
context_params * p = reinterpret_cast<context_params*>(c);
p->set(param_id, param_value);
}
catch (z3_exception & ex) {
// The error handler is only available for contexts
// Just throw a warning.
warning_msg("%s", ex.msg());
}
}
强制转换回Z3_config
。我不是专家,但这可能有用,因为struct and class are almost the same位于引擎盖下面。
另一方面,在示例文件context_params
中,他们像这样使用test_capi.c
Z3_global_param_set
在使用....
cfg = Z3_mk_config();
....
/*
The current model finder for quantified formulas cannot handle injectivity.
So, we are limiting the number of iterations to avoid a long "wait".
*/
Z3_global_param_set("smt.mbqi.max_iterations", "10");
ctx = mk_context_custom(cfg, error_handler);
Z3_del_config(cfg);
s = mk_solver(ctx);
进行配置时,他们仍然在创建上下文之前仍使用Z3_mk_config
。因此,我想说的是,使用Z3_global_param_set
来构造Z3_mk_config
并没有什么问题,而文档所说的是,当您要全局设置某些内容时,不要访问Z3_config
结构本身,因为无论如何您都无法将其转换为Z3_config
;使用context_params
代替。并且,当您要为特定的上下文设置特定的内容时,请使用Z3_global_param_set
。
问题仍然是,为什么我们要在结构和类之间切换?我不知道。我对C ++一点都不熟悉,但是我猜测,如果不是C API本身,它是为了使Z3_set_param_value
部分for the Python API bindings有效。