Skip to content

Commit e154903

Browse files
eaferwing328
andauthored
Fix a few issues with the C generator (part 8) (#20378)
* [C] Deprecate *_create() to avoid *_free() confusion The behaviour of *_free() doesn't match *_create(), so the user should avoid using them together. But they still need *_free() to clean up library-allocated objects, so add a _library_owned flag to each struct as an attempt to tell them apart. This isn't perfect though, because the user may neglect to zero the field, but they would still see a warning once in a while so it serves its purpose. To prevent the new deprecation warnings (intended for the user) from showing up during the library build itself, define a new family of *_create_internal() functions, and turn *_create() into simple wrappers. * Update samples * add eafer to c technical committee --------- Co-authored-by: William Cheng <wing328hk@gmail.com>
1 parent 85c81be commit e154903

35 files changed

+450
-52
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,7 @@ If you want to join the committee, please kindly apply by sending an email to te
12101210
| Android | @jaz-ah (2017/09) |
12111211
| Apex | |
12121212
| Bash | @frol (2017/07) @bkryza (2017/08) @kenjones-cisco (2017/09) |
1213-
| C | @zhemant (2018/11) @ityuhui (2019/12) @michelealbano (2020/03) |
1213+
| C | @zhemant (2018/11) @ityuhui (2019/12) @michelealbano (2020/03) @eafer (2024/12) |
12141214
| C++ | @ravinikam (2017/07) @stkrwork (2017/07) @etherealjoy (2018/02) @martindelille (2018/03) @muttleyxd (2019/08) |
12151215
| C# | @mandrean (2017/08) @shibayan (2020/02) @Blackclaws (2021/03) @lucamazzanti (2021/05) @iBicha (2023/07) |
12161216
| Clojure | |

modules/openapi-generator/src/main/resources/C-libcurl/model-body.mustache

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ char* {{classname}}_{{name}}_ToString({{projectName}}_{{classVarName}}_{{enumNam
119119
{{/isContainer}}
120120
{{/vars}}
121121

122-
{{classname}}_t *{{classname}}_create(
122+
static {{classname}}_t *{{classname}}_create_internal(
123123
{{#vars}}
124124
{{^isContainer}}
125125
{{^isPrimitiveType}}
@@ -205,14 +205,103 @@ char* {{classname}}_{{name}}_ToString({{projectName}}_{{classVarName}}_{{enumNam
205205
{{classname}}_local_var->{{{name}}} = {{{name}}};
206206
{{/vars}}
207207

208+
{{classname}}_local_var->_library_owned = 1;
208209
return {{classname}}_local_var;
209210
}
210211

212+
__attribute__((deprecated)) {{classname}}_t *{{classname}}_create(
213+
{{#vars}}
214+
{{^isContainer}}
215+
{{^isPrimitiveType}}
216+
{{#isModel}}
217+
{{#isEnum}}
218+
{{projectName}}_{{classVarName}}_{{enumName}}_e {{name}}{{^-last}},{{/-last}}
219+
{{/isEnum}}
220+
{{^isEnum}}
221+
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
222+
{{/isEnum}}
223+
{{/isModel}}
224+
{{^isModel}}
225+
{{^isFreeFormObject}}
226+
{{^isEnum}}
227+
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
228+
{{/isEnum}}
229+
{{#isEnum}}
230+
{{projectName}}_{{dataType}}_{{enumName}}_e {{name}}{{^-last}},{{/-last}}
231+
{{/isEnum}}
232+
{{/isFreeFormObject}}
233+
{{/isModel}}
234+
{{#isUuid}}
235+
{{datatype}} *{{name}}{{^-last}},{{/-last}}
236+
{{/isUuid}}
237+
{{#isEmail}}
238+
{{datatype}} *{{name}}{{^-last}},{{/-last}}
239+
{{/isEmail}}
240+
{{#isFreeFormObject}}
241+
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
242+
{{/isFreeFormObject}}
243+
{{/isPrimitiveType}}
244+
{{#isPrimitiveType}}
245+
{{#isNumeric}}
246+
{{datatype}} {{name}}{{^-last}},{{/-last}}
247+
{{/isNumeric}}
248+
{{#isBoolean}}
249+
{{datatype}} {{name}}{{^-last}},{{/-last}}
250+
{{/isBoolean}}
251+
{{#isEnum}}
252+
{{#isString}}
253+
{{projectName}}_{{classVarName}}_{{enumName}}_e {{name}}{{^-last}},{{/-last}}
254+
{{/isString}}
255+
{{/isEnum}}
256+
{{^isEnum}}
257+
{{#isString}}
258+
{{datatype}} *{{name}}{{^-last}},{{/-last}}
259+
{{/isString}}
260+
{{/isEnum}}
261+
{{#isByteArray}}
262+
{{datatype}} *{{name}}{{^-last}},{{/-last}}
263+
{{/isByteArray}}
264+
{{#isBinary}}
265+
{{datatype}} {{name}}{{^-last}},{{/-last}}
266+
{{/isBinary}}
267+
{{#isDate}}
268+
{{datatype}} *{{name}}{{^-last}},{{/-last}}
269+
{{/isDate}}
270+
{{#isDateTime}}
271+
{{datatype}} *{{name}}{{^-last}},{{/-last}}
272+
{{/isDateTime}}
273+
{{/isPrimitiveType}}
274+
{{/isContainer}}
275+
{{#isContainer}}
276+
{{#isArray}}
277+
{{#isPrimitiveType}}
278+
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
279+
{{/isPrimitiveType}}
280+
{{^isPrimitiveType}}
281+
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
282+
{{/isPrimitiveType}}
283+
{{/isArray}}
284+
{{#isMap}}
285+
{{datatype}} {{name}}{{^-last}},{{/-last}}
286+
{{/isMap}}
287+
{{/isContainer}}
288+
{{/vars}}
289+
) {
290+
return {{classname}}_create_internal (
291+
{{#vars}}
292+
{{name}}{{^-last}},{{/-last}}
293+
{{/vars}}
294+
);
295+
}
211296

212297
void {{classname}}_free({{classname}}_t *{{classname}}) {
213298
if(NULL == {{classname}}){
214299
return ;
215300
}
301+
if({{classname}}->_library_owned != 1){
302+
fprintf(stderr, "WARNING: %s() does NOT free objects allocated by the user\n", "{{classname}}_free");
303+
return ;
304+
}
216305
listEntry_t *listEntry;
217306
{{#vars}}
218307
{{^isContainer}}
@@ -859,7 +948,7 @@ fail:
859948

860949
{{/vars}}
861950

862-
{{classname}}_local_var = {{classname}}_create (
951+
{{classname}}_local_var = {{classname}}_create_internal (
863952
{{#vars}}
864953
{{^isContainer}}
865954
{{^isPrimitiveType}}

modules/openapi-generator/src/main/resources/C-libcurl/model-header.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,10 @@ typedef struct {{classname}}_t {
154154
{{/isContainer}}
155155
{{/vars}}
156156

157+
int _library_owned; // Is the library responsible for freeing this object?
157158
} {{classname}}_t;
158159

159-
{{classname}}_t *{{classname}}_create(
160+
__attribute__((deprecated)) {{classname}}_t *{{classname}}_create(
160161
{{#vars}}
161162
{{^isContainer}}
162163
{{^isPrimitiveType}}

samples/client/petstore/c-useJsonUnformatted/model/api_response.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77

8-
api_response_t *api_response_create(
8+
static api_response_t *api_response_create_internal(
99
int code,
1010
char *type,
1111
char *message
@@ -18,14 +18,30 @@ api_response_t *api_response_create(
1818
api_response_local_var->type = type;
1919
api_response_local_var->message = message;
2020

21+
api_response_local_var->_library_owned = 1;
2122
return api_response_local_var;
2223
}
2324

25+
__attribute__((deprecated)) api_response_t *api_response_create(
26+
int code,
27+
char *type,
28+
char *message
29+
) {
30+
return api_response_create_internal (
31+
code,
32+
type,
33+
message
34+
);
35+
}
2436

2537
void api_response_free(api_response_t *api_response) {
2638
if(NULL == api_response){
2739
return ;
2840
}
41+
if(api_response->_library_owned != 1){
42+
fprintf(stderr, "WARNING: %s() does NOT free objects allocated by the user\n", "api_response_free");
43+
return ;
44+
}
2945
listEntry_t *listEntry;
3046
if (api_response->type) {
3147
free(api_response->type);
@@ -113,7 +129,7 @@ api_response_t *api_response_parseFromJSON(cJSON *api_responseJSON){
113129
}
114130

115131

116-
api_response_local_var = api_response_create (
132+
api_response_local_var = api_response_create_internal (
117133
code ? code->valuedouble : 0,
118134
type && !cJSON_IsNull(type) ? strdup(type->valuestring) : NULL,
119135
message && !cJSON_IsNull(message) ? strdup(message->valuestring) : NULL

samples/client/petstore/c-useJsonUnformatted/model/api_response.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ typedef struct api_response_t {
2323
char *type; // string
2424
char *message; // string
2525

26+
int _library_owned; // Is the library responsible for freeing this object?
2627
} api_response_t;
2728

28-
api_response_t *api_response_create(
29+
__attribute__((deprecated)) api_response_t *api_response_create(
2930
int code,
3031
char *type,
3132
char *message

samples/client/petstore/c-useJsonUnformatted/model/category.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77

8-
category_t *category_create(
8+
static category_t *category_create_internal(
99
long id,
1010
char *name
1111
) {
@@ -16,14 +16,28 @@ category_t *category_create(
1616
category_local_var->id = id;
1717
category_local_var->name = name;
1818

19+
category_local_var->_library_owned = 1;
1920
return category_local_var;
2021
}
2122

23+
__attribute__((deprecated)) category_t *category_create(
24+
long id,
25+
char *name
26+
) {
27+
return category_create_internal (
28+
id,
29+
name
30+
);
31+
}
2232

2333
void category_free(category_t *category) {
2434
if(NULL == category){
2535
return ;
2636
}
37+
if(category->_library_owned != 1){
38+
fprintf(stderr, "WARNING: %s() does NOT free objects allocated by the user\n", "category_free");
39+
return ;
40+
}
2741
listEntry_t *listEntry;
2842
if (category->name) {
2943
free(category->name);
@@ -87,7 +101,7 @@ category_t *category_parseFromJSON(cJSON *categoryJSON){
87101
}
88102

89103

90-
category_local_var = category_create (
104+
category_local_var = category_create_internal (
91105
id ? id->valuedouble : 0,
92106
name && !cJSON_IsNull(name) ? strdup(name->valuestring) : NULL
93107
);

samples/client/petstore/c-useJsonUnformatted/model/category.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ typedef struct category_t {
2222
long id; //numeric
2323
char *name; // string
2424

25+
int _library_owned; // Is the library responsible for freeing this object?
2526
} category_t;
2627

27-
category_t *category_create(
28+
__attribute__((deprecated)) category_t *category_create(
2829
long id,
2930
char *name
3031
);

samples/client/petstore/c-useJsonUnformatted/model/mapped_model.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77

8-
MappedModel_t *MappedModel_create(
8+
static MappedModel_t *MappedModel_create_internal(
99
int another_property,
1010
char *uuid_property
1111
) {
@@ -16,14 +16,28 @@ MappedModel_t *MappedModel_create(
1616
MappedModel_local_var->another_property = another_property;
1717
MappedModel_local_var->uuid_property = uuid_property;
1818

19+
MappedModel_local_var->_library_owned = 1;
1920
return MappedModel_local_var;
2021
}
2122

23+
__attribute__((deprecated)) MappedModel_t *MappedModel_create(
24+
int another_property,
25+
char *uuid_property
26+
) {
27+
return MappedModel_create_internal (
28+
another_property,
29+
uuid_property
30+
);
31+
}
2232

2333
void MappedModel_free(MappedModel_t *MappedModel) {
2434
if(NULL == MappedModel){
2535
return ;
2636
}
37+
if(MappedModel->_library_owned != 1){
38+
fprintf(stderr, "WARNING: %s() does NOT free objects allocated by the user\n", "MappedModel_free");
39+
return ;
40+
}
2741
listEntry_t *listEntry;
2842
if (MappedModel->uuid_property) {
2943
free(MappedModel->uuid_property);
@@ -87,7 +101,7 @@ MappedModel_t *MappedModel_parseFromJSON(cJSON *MappedModelJSON){
87101
}
88102

89103

90-
MappedModel_local_var = MappedModel_create (
104+
MappedModel_local_var = MappedModel_create_internal (
91105
another_property ? another_property->valuedouble : 0,
92106
uuid_property && !cJSON_IsNull(uuid_property) ? strdup(uuid_property->valuestring) : NULL
93107
);

samples/client/petstore/c-useJsonUnformatted/model/mapped_model.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ typedef struct MappedModel_t {
2222
int another_property; //numeric
2323
char *uuid_property; // string
2424

25+
int _library_owned; // Is the library responsible for freeing this object?
2526
} MappedModel_t;
2627

27-
MappedModel_t *MappedModel_create(
28+
__attribute__((deprecated)) MappedModel_t *MappedModel_create(
2829
int another_property,
2930
char *uuid_property
3031
);

samples/client/petstore/c-useJsonUnformatted/model/model_with_set_propertes.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77

8-
model_with_set_propertes_t *model_with_set_propertes_create(
8+
static model_with_set_propertes_t *model_with_set_propertes_create_internal(
99
list_t *tag_set,
1010
list_t *string_set
1111
) {
@@ -16,14 +16,28 @@ model_with_set_propertes_t *model_with_set_propertes_create(
1616
model_with_set_propertes_local_var->tag_set = tag_set;
1717
model_with_set_propertes_local_var->string_set = string_set;
1818

19+
model_with_set_propertes_local_var->_library_owned = 1;
1920
return model_with_set_propertes_local_var;
2021
}
2122

23+
__attribute__((deprecated)) model_with_set_propertes_t *model_with_set_propertes_create(
24+
list_t *tag_set,
25+
list_t *string_set
26+
) {
27+
return model_with_set_propertes_create_internal (
28+
tag_set,
29+
string_set
30+
);
31+
}
2232

2333
void model_with_set_propertes_free(model_with_set_propertes_t *model_with_set_propertes) {
2434
if(NULL == model_with_set_propertes){
2535
return ;
2636
}
37+
if(model_with_set_propertes->_library_owned != 1){
38+
fprintf(stderr, "WARNING: %s() does NOT free objects allocated by the user\n", "model_with_set_propertes_free");
39+
return ;
40+
}
2741
listEntry_t *listEntry;
2842
if (model_with_set_propertes->tag_set) {
2943
list_ForEach(listEntry, model_with_set_propertes->tag_set) {
@@ -146,7 +160,7 @@ model_with_set_propertes_t *model_with_set_propertes_parseFromJSON(cJSON *model_
146160
}
147161

148162

149-
model_with_set_propertes_local_var = model_with_set_propertes_create (
163+
model_with_set_propertes_local_var = model_with_set_propertes_create_internal (
150164
tag_set ? tag_setList : NULL,
151165
string_set ? string_setList : NULL
152166
);

samples/client/petstore/c-useJsonUnformatted/model/model_with_set_propertes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ typedef struct model_with_set_propertes_t {
2323
list_t *tag_set; //nonprimitive container
2424
list_t *string_set; //primitive container
2525

26+
int _library_owned; // Is the library responsible for freeing this object?
2627
} model_with_set_propertes_t;
2728

28-
model_with_set_propertes_t *model_with_set_propertes_create(
29+
__attribute__((deprecated)) model_with_set_propertes_t *model_with_set_propertes_create(
2930
list_t *tag_set,
3031
list_t *string_set
3132
);

0 commit comments

Comments
 (0)