Skip to content

Commit 01ec923

Browse files
committed
Add byRef and byValue static methods to Structs
1 parent 7ff5520 commit 01ec923

File tree

4 files changed

+113
-17
lines changed

4 files changed

+113
-17
lines changed

examples/subclass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ static function definition()
3232
var_dump($tm);
3333

3434
$lib = new MFFI\Library();
35-
$asctime = $lib->bind('asctime', [ TimeStruct::class ], MFFI\Type::TYPE_STRING);
35+
$asctime = $lib->bind('asctime', [ TimeStruct::byValue() ], MFFI\Type::TYPE_STRING);
3636
var_dump($asctime($tm));
3737

mffi_library.c

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ PHP_METHOD(MFFI_Library, bind)
5555
{
5656
zend_string *func_name = NULL;
5757
zval *args = NULL, *current_arg = NULL, *return_type = NULL;
58-
HashTable *args_hash = NULL;
58+
HashTable *args_hash = NULL, *ht = NULL;
5959
php_mffi_library_object *intern = NULL;
6060
php_mffi_function_object *function = NULL;
6161
php_mffi_struct_definition *def = NULL;
@@ -103,26 +103,61 @@ PHP_METHOD(MFFI_Library, bind)
103103
function->php_arg_types[i] = Z_LVAL_P(current_arg);
104104
break;
105105

106+
case IS_ARRAY:
107+
ht = Z_ARRVAL_P(current_arg);
108+
zval *tmp;
109+
110+
if (zend_hash_num_elements(ht) != 2) {
111+
zend_throw_exception_ex(mffi_ce_exception, 0, "Invalid argument definition for %s", func_name->val);
112+
goto cleanup;
113+
}
114+
115+
tmp = zend_hash_index_find(ht, 0);
116+
117+
if (Z_TYPE_P(tmp) != IS_STRING) {
118+
zend_throw_exception_ex(mffi_ce_exception, 0, "Invalid argument definition for %s", func_name->val);
119+
goto cleanup;
120+
}
121+
122+
def = zend_hash_find_ptr(MFFI_G(struct_definitions), Z_STR_P(tmp));
123+
124+
if (def == NULL) {
125+
zend_throw_exception_ex(mffi_ce_exception, 0, "Struct definition for %s not found", Z_STRVAL_P(tmp));
126+
goto cleanup;
127+
}
128+
129+
tmp = zend_hash_index_find(ht, 1);
130+
131+
if (Z_TYPE_P(tmp) != IS_LONG) {
132+
zend_throw_exception_ex(mffi_ce_exception, 0, "Invalid argument definition for %s", func_name->val);
133+
goto cleanup;
134+
}
135+
136+
if (Z_LVAL_P(tmp) == PHP_MFFI_BY_VALUE) {
137+
function->ffi_arg_types[i] = &def->type;
138+
function->php_arg_types[i] = FFI_TYPE_STRUCT;
139+
} else {
140+
function->ffi_arg_types[i] = &ffi_type_pointer;
141+
function->php_arg_types[i] = FFI_TYPE_POINTER;
142+
}
143+
144+
break;
145+
106146
case IS_STRING:
107147
def = zend_hash_find_ptr(MFFI_G(struct_definitions), Z_STR_P(current_arg));
108148

109149
if (def == NULL) {
110150
zend_throw_exception_ex(mffi_ce_exception, 0, "Struct definition for %s not found", Z_STRVAL_P(current_arg));
111-
efree(function->php_arg_types);
112-
efree(function->ffi_arg_types);
113-
return;
151+
goto cleanup;
114152
}
115153

116-
// function->ffi_arg_types[i] = &def->type;
117154
function->ffi_arg_types[i] = &ffi_type_pointer;
118155
function->php_arg_types[i] = FFI_TYPE_POINTER;
119156
break;
120157

121158
default:
122159
zend_throw_exception(mffi_ce_exception, "Unsupported type", 1);
123-
efree(function->php_arg_types);
124-
efree(function->ffi_arg_types);
125-
return;
160+
goto cleanup;
126161
}
127162

128163
i++;
@@ -152,9 +187,7 @@ PHP_METHOD(MFFI_Library, bind)
152187

153188
if (def == NULL) {
154189
zend_throw_exception_ex(mffi_ce_exception, 0, "Struct definition %s not found", Z_STRVAL_P(return_type));
155-
efree(function->php_arg_types);
156-
efree(function->ffi_arg_types);
157-
return;
190+
goto cleanup;
158191
}
159192

160193
function->return_type = &ffi_type_pointer;
@@ -170,9 +203,15 @@ PHP_METHOD(MFFI_Library, bind)
170203
zend_throw_exception(mffi_ce_exception, "Something went wrong preparing the function", 1);
171204
efree(function->php_arg_types);
172205
efree(function->ffi_arg_types);
173-
return;
174206
}
175207

208+
return;
209+
210+
cleanup:
211+
efree(function->php_arg_types);
212+
efree(function->ffi_arg_types);
213+
return;
214+
176215
}
177216
/* }}} */
178217

mffi_struct.c

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,57 @@ PHP_METHOD(MFFI_Struct, pointer)
6565
}
6666
/* }}} */
6767

68+
/* {{{ PHP_METHOD(MFFI_Struct, byRef) */
69+
PHP_METHOD(MFFI_Struct, byRef)
70+
{
71+
php_mffi_struct_definition *def;
72+
73+
PHP_MFFI_ERROR_HANDLING();
74+
if (zend_parse_parameters_none() == FAILURE) {
75+
PHP_MFFI_RESTORE_ERRORS();
76+
return;
77+
}
78+
PHP_MFFI_RESTORE_ERRORS();
79+
80+
def = zend_hash_find_ptr(MFFI_G(struct_definitions), EX(called_scope)->name);
81+
if (def == NULL) {
82+
zval tmp;
83+
object_init_ex(&tmp, EX(called_scope));
84+
php_mffi_struct_get_definition(Z_OBJ(tmp));
85+
zval_ptr_dtor(&tmp);
86+
}
87+
88+
array_init(return_value);
89+
add_next_index_string(return_value, EX(called_scope)->name->val);
90+
add_next_index_long(return_value, PHP_MFFI_BY_REFERENCE);
91+
}
92+
/* }}} */
93+
94+
/* {{{ PHP_METHOD(MFFI_Struct, byValue) */
95+
PHP_METHOD(MFFI_Struct, byValue)
96+
{
97+
php_mffi_struct_definition *def;
98+
99+
PHP_MFFI_ERROR_HANDLING();
100+
if (zend_parse_parameters_none() == FAILURE) {
101+
PHP_MFFI_RESTORE_ERRORS();
102+
return;
103+
}
104+
PHP_MFFI_RESTORE_ERRORS();
105+
106+
def = zend_hash_find_ptr(MFFI_G(struct_definitions), EX(called_scope)->name);
107+
if (def == NULL) {
108+
zval tmp;
109+
object_init_ex(&tmp, EX(called_scope));
110+
php_mffi_struct_get_definition(Z_OBJ(tmp));
111+
zval_ptr_dtor(&tmp);
112+
}
113+
114+
array_init(return_value);
115+
add_next_index_string(return_value, EX(called_scope)->name->val);
116+
add_next_index_long(return_value, PHP_MFFI_BY_VALUE);
117+
}
118+
/* }}} */
68119

69120
/* {{{ PHP_METHOD(MFFI_Struct, define) */
70121
PHP_METHOD(MFFI_Struct, define)
@@ -96,9 +147,11 @@ PHP_METHOD(MFFI_Struct, define)
96147

97148
/* {{{ */
98149
const zend_function_entry mffi_struct_methods[] = {
99-
PHP_ME(MFFI_Struct, define, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
100-
PHP_ME(MFFI_Struct, pointer, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
101-
PHP_ME(MFFI_Struct, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
150+
PHP_ME(MFFI_Struct, define, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
151+
PHP_ME(MFFI_Struct, pointer, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
152+
PHP_ME(MFFI_Struct, byRef, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
153+
PHP_ME(MFFI_Struct, byValue, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
154+
PHP_ME(MFFI_Struct, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
102155
PHP_FE_END
103156
};
104157
/* }}} */
@@ -165,7 +218,8 @@ static php_mffi_struct_definition *php_mffi_make_struct_definition(zval *element
165218
return NULL;
166219
}
167220

168-
if (Z_TYPE_P(current_elem) != IS_LONG && Z_TYPE_P(current_elem) != IS_STRING) {
221+
/* TODO: Support user-defined structs */
222+
if (Z_TYPE_P(current_elem) != IS_LONG /* && Z_TYPE_P(current_elem) != IS_STRING */) {
169223
zend_throw_exception_ex(mffi_ce_exception, 0, "Unsupported type for element %s", string_key->val);
170224
return NULL;
171225
}

php_mffi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ typedef struct _php_mffi_struct_object {
103103

104104
#define PHP_MFFI_TYPE_STRING 64
105105

106+
#define PHP_MFFI_BY_REFERENCE 0
107+
#define PHP_MFFI_BY_VALUE 1
108+
106109
#endif /* PHP_mffi_H */
107110

108111
/*

0 commit comments

Comments
 (0)