Skip to content

Commit 58fde42

Browse files
fix: improve generated C extension code (#1698)
1 parent 291dd4e commit 58fde42

3 files changed

Lines changed: 19 additions & 45 deletions

File tree

internal/extgen/hfile_test.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ func TestHeaderGenerator_BuildContent(t *testing.T) {
4444
"#define _SIMPLE_H",
4545
"#include <php.h>",
4646
"extern zend_module_entry ext_module_entry;",
47-
"typedef struct go_value go_value;",
48-
"typedef struct go_string {",
49-
"size_t len;",
50-
"char *data;",
51-
"} go_string;",
5247
"#endif",
5348
},
5449
},
@@ -134,11 +129,6 @@ func TestHeaderGenerator_BasicStructure(t *testing.T) {
134129
expectedElements := []string{
135130
"#include <php.h>",
136131
"extern zend_module_entry ext_module_entry;",
137-
"typedef struct go_value go_value;",
138-
"typedef struct go_string {",
139-
"size_t len;",
140-
"char *data;",
141-
"} go_string;",
142132
}
143133

144134
for _, element := range expectedElements {
@@ -209,9 +199,6 @@ func TestHeaderGenerator_ContentValidation(t *testing.T) {
209199
assert.Equal(t, 1, strings.Count(content, "#define"), "Header should have exactly one #define")
210200
assert.Equal(t, 1, strings.Count(content, "#endif"), "Header should have exactly one #endif")
211201
assert.False(t, strings.Contains(content, "{{") || strings.Contains(content, "}}"), "Generated header contains unresolved template syntax")
212-
assert.Contains(t, content, "typedef struct go_string {", "Header should contain go_string typedef")
213-
assert.Contains(t, content, "size_t len;", "Header should contain len field in go_string")
214-
assert.Contains(t, content, "char *data;", "Header should contain data field in go_string")
215202
}
216203

217204
func TestHeaderGenerator_SpecialCharacterHandling(t *testing.T) {
@@ -278,7 +265,6 @@ func TestHeaderGenerator_MinimalContent(t *testing.T) {
278265
"#define _MINIMAL_H",
279266
"#include <php.h>",
280267
"extern zend_module_entry ext_module_entry;",
281-
"typedef struct go_value go_value;",
282268
"#endif",
283269
}
284270

@@ -302,11 +288,6 @@ func testHeaderBasicStructure(t *testing.T, content, baseName string) {
302288
"#define _" + headerGuard,
303289
"#include <php.h>",
304290
"extern zend_module_entry ext_module_entry;",
305-
"typedef struct go_value go_value;",
306-
"typedef struct go_string {",
307-
"size_t len;",
308-
"char *data;",
309-
"} go_string;",
310291
"#endif",
311292
}
312293

internal/extgen/templates/extension.c.tpl

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,19 @@
88

99
{{- if .Classes}}
1010

11+
#define VALIDATE_GO_HANDLE(intern) \
12+
do { \
13+
if ((intern)->go_handle == 0) { \
14+
zend_throw_error(NULL, "Go object not found in registry"); \
15+
RETURN_THROWS(); \
16+
} \
17+
} while (0)
18+
1119
static zend_object_handlers object_handlers_{{.BaseName}};
1220

1321
typedef struct {
1422
uintptr_t go_handle;
15-
char* class_name;
16-
zend_object std; /* This MUST be the last struct field to memory alignement problems */
23+
zend_object std; /* This must be the last field in the structure: the property store starts at this offset */
1724
} {{.BaseName}}_object;
1825

1926
static inline {{.BaseName}}_object *{{.BaseName}}_object_from_obj(zend_object *obj) {
@@ -28,33 +35,24 @@ static zend_object *{{.BaseName}}_create_object(zend_class_entry *ce) {
2835

2936
intern->std.handlers = &object_handlers_{{.BaseName}};
3037
intern->go_handle = 0; /* will be set in __construct */
31-
intern->class_name = estrdup(ZSTR_VAL(ce->name));
32-
38+
3339
return &intern->std;
3440
}
3541

3642
static void {{.BaseName}}_free_object(zend_object *object) {
3743
{{.BaseName}}_object *intern = {{.BaseName}}_object_from_obj(object);
38-
39-
if (intern->class_name) {
40-
efree(intern->class_name);
41-
}
42-
44+
4345
if (intern->go_handle != 0) {
4446
removeGoObject(intern->go_handle);
4547
}
4648

4749
zend_object_std_dtor(&intern->std);
4850
}
4951

50-
static zend_function *{{.BaseName}}_get_method(zend_object **object, zend_string *method, const zval *key) {
51-
return zend_std_get_method(object, method, key);
52-
}
53-
5452
void init_object_handlers() {
5553
memcpy(&object_handlers_{{.BaseName}}, &std_object_handlers, sizeof(zend_object_handlers));
56-
object_handlers_{{.BaseName}}.get_method = {{.BaseName}}_get_method;
5754
object_handlers_{{.BaseName}}.free_obj = {{.BaseName}}_free_object;
55+
object_handlers_{{.BaseName}}.clone_obj = NULL;
5856
object_handlers_{{.BaseName}}.offset = offsetof({{.BaseName}}_object, std);
5957
}
6058
{{- end}}
@@ -67,18 +65,20 @@ PHP_METHOD({{.Name}}, __construct) {
6765
}
6866

6967
{{$.BaseName}}_object *intern = {{$.BaseName}}_object_from_obj(Z_OBJ_P(ZEND_THIS));
70-
68+
69+
/* Constructor is called more than once, make it no-op */
70+
if (intern->go_handle != 0) {
71+
return;
72+
}
73+
7174
intern->go_handle = create_{{.GoStruct}}_object();
7275
}
7376

7477
{{ range .Methods}}
7578
PHP_METHOD({{.ClassName}}, {{.PhpName}}) {
7679
{{$.BaseName}}_object *intern = {{$.BaseName}}_object_from_obj(Z_OBJ_P(ZEND_THIS));
7780

78-
if (intern->go_handle == 0) {
79-
zend_throw_error(NULL, "Go object not found in registry");
80-
RETURN_THROWS();
81-
}
81+
VALIDATE_GO_HANDLE(intern);
8282

8383
{{- if .Params -}}
8484
{{range $i, $param := .Params -}}

internal/extgen/templates/extension.h.tpl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@
66

77
extern zend_module_entry ext_module_entry;
88

9-
typedef struct go_value go_value;
10-
11-
typedef struct go_string {
12-
size_t len;
13-
char *data;
14-
} go_string;
15-
169
{{if .Constants}}
1710
/* User defined constants */{{end}}
1811
{{range .Constants}}#define {{.Name}} {{.CValue}}

0 commit comments

Comments
 (0)