RNA: support passing template arguments to functions

The goal is to allow passing template parameters in the string that is passed
to `RNA_def_function` in rna code. This can reduce redundancy (e.g. when used
together with #113114). Only "simple" template parameters are supported,
i.e. only ones that do not contain a nested `,`.

Function names passed to e.g. `RNA_def_property_pointer_funcs` and
`RNA_def_property_update` happen to support this already without further changes.

Pull Request: https://projects.blender.org/blender/blender/pulls/113121
This commit is contained in:
Jacques Lucke
2023-10-01 23:24:19 +02:00
parent 8a2e81b16b
commit 690a3ddf7e

View File

@@ -3010,6 +3010,25 @@ static void rna_def_property_wrapper_funcs(FILE *f, StructDefRNA *dsrna, Propert
}
}
/**
* Counts the number of template arguments by looking at `<` and `,` characters in the name. More
* complex template arguments that contains `,` themselves are not handled yet.
*/
static int count_template_args(const char *function_name)
{
BLI_assert(function_name != nullptr);
if (!strstr(function_name, "<")) {
return 0;
}
int count = 1;
for (const char *c = function_name; *c; c++) {
if (*c == ',') {
count++;
}
}
return count;
}
static void rna_def_function_wrapper_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA *dfunc)
{
StructRNA *srna = dsrna->srna;
@@ -3026,7 +3045,10 @@ static void rna_def_function_wrapper_funcs(FILE *f, StructDefRNA *dsrna, Functio
rna_construct_wrapper_function_name(
funcname, sizeof(funcname), srna->identifier, func->identifier, "func");
fprintf(f, "RNA_EXTERN_C ");
/* A function with templates cannot have C linkage. */
if (!(dfunc->call && count_template_args(dfunc->call) > 0)) {
fprintf(f, "RNA_EXTERN_C ");
}
rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 0);
fprintf(f, "\n{\n");
@@ -3785,6 +3807,19 @@ static void rna_generate_static_parameter_prototypes(FILE *f,
dsrna = rna_find_struct_def(srna);
func = dfunc->func;
const int template_args_num = dfunc->call ? count_template_args(dfunc->call) : 0;
if (!name_override && template_args_num > 0) {
/* The template names are called A, B, C, etc. */
BLI_assert(template_args_num <= 26);
fprintf(f, "template<typename A");
char template_name = 'B';
for (int i = 0; i < template_args_num - 1; i++) {
fprintf(f, ", typename %c", template_name);
template_name++;
}
fprintf(f, "> ");
}
/* return type */
LISTBASE_FOREACH (PropertyDefRNA *, dparm, &dfunc->cont.properties) {
if (dparm->prop == func->c_ret) {
@@ -3810,7 +3845,15 @@ static void rna_generate_static_parameter_prototypes(FILE *f,
/* function name */
if (name_override == nullptr || name_override[0] == '\0') {
fprintf(f, "%s(", dfunc->call);
/* Here we only need the function name without the template parameters. */
const char *template_begin = strstr(dfunc->call, "<");
if (template_begin) {
const int num_chars = template_begin - dfunc->call;
fprintf(f, "%.*s(", num_chars, dfunc->call);
}
else {
fprintf(f, "%s(", dfunc->call);
}
}
else {
fprintf(f, "%s(", name_override);