├── README.md ├── config.m4 ├── hello.c ├── php.ini └── php_hello.h /README.md: -------------------------------------------------------------------------------- 1 | # Compile 2 | 3 | phpize 4 | ./configure --enable-hello 5 | make 6 | 7 | # Tutorial 1 8 | 9 | http://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/ 10 | 11 | # Run 12 | 13 | php -c php.ini -r "echo hello_world();" 14 | Hello World 15 | 16 | php -c php.ini -r "var_dump( hello_bool() );" 17 | bool(true) 18 | 19 | php -c php.ini -r "echo hello_long();" 20 | 42 21 | 22 | php -c php.ini -r "echo hello_double();" 23 | 3.1415926535 24 | 25 | php -c php.ini -r "var_dump( hello_null() );" 26 | NULL 27 | 28 | 29 | # Tutorial 2 30 | 31 | http://devzone.zend.com/317/extension-writing-part-ii-parameters-arrays-and-zvals/ 32 | http://devzone.zend.com/318/extension-writing-part-ii-parameters-arrays-and-zvals-continued/ 33 | 34 | php -c php.ini -r "hello_greetme('Joe');" 35 | Hello Joe 36 | 37 | php -c php.ini -r "echo hello_add(2, 4.1);" 38 | 6.1 39 | 40 | php -c php.ini -r "echo hello_add(2, 4.1, true);" 41 | 6 42 | 43 | php -c php.ini -r "var_dump(hello_array());" 44 | 45 | array(6) { 46 | [42]=> 47 | int(123) 48 | [43]=> 49 | string(33) "I should now be found at index 43" 50 | [44]=> 51 | string(10) "I'm at 44!" 52 | [45]=> 53 | string(10) "Forty Five" 54 | ["pi"]=> 55 | float(3.1415926535) 56 | ["subarray"]=> 57 | array(1) { 58 | [0]=> 59 | string(5) "hello" 60 | } 61 | } 62 | 63 | 64 | Show hello_array_strings: 65 | 66 | = 20010901 32 | STANDARD_MODULE_HEADER, 33 | #endif 34 | PHP_HELLO_WORLD_EXTNAME, 35 | hello_functions, 36 | PHP_MINIT(hello), 37 | PHP_MSHUTDOWN(hello), 38 | PHP_RINIT(hello), 39 | NULL, 40 | NULL, 41 | #if ZEND_MODULE_API_NO >= 20010901 42 | PHP_HELLO_WORLD_VERSION, 43 | #endif 44 | STANDARD_MODULE_PROPERTIES 45 | }; 46 | 47 | #ifdef COMPILE_DL_HELLO 48 | ZEND_GET_MODULE(hello) 49 | #endif 50 | 51 | PHP_INI_BEGIN() 52 | PHP_INI_ENTRY("hello.greeting", "Hello World", PHP_INI_ALL, NULL) 53 | STD_PHP_INI_ENTRY("hello.direction", "1", PHP_INI_ALL, 54 | OnUpdateBool, direction, zend_hello_globals, hello_globals) 55 | PHP_INI_END() 56 | 57 | static void php_hello_init_globals(zend_hello_globals *hello_globals) 58 | { 59 | hello_globals->direction = 1; 60 | } 61 | 62 | PHP_RINIT_FUNCTION(hello) 63 | { 64 | HELLO_G(counter) = 0; 65 | 66 | return SUCCESS; 67 | } 68 | 69 | PHP_MINIT_FUNCTION(hello) 70 | { 71 | le_hello_person = zend_register_list_destructors_ex(NULL, NULL, 72 | PHP_HELLO_PERSON_RES_NAME, module_number); 73 | ZEND_INIT_MODULE_GLOBALS(hello, php_hello_init_globals, NULL); 74 | REGISTER_INI_ENTRIES(); 75 | 76 | return SUCCESS; 77 | } 78 | 79 | PHP_MSHUTDOWN_FUNCTION(hello) 80 | { 81 | UNREGISTER_INI_ENTRIES(); 82 | 83 | return SUCCESS; 84 | } 85 | 86 | PHP_FUNCTION(hello_world) 87 | { 88 | RETURN_STRING(INI_STR("hello.greeting"), 1); 89 | } 90 | 91 | PHP_FUNCTION(hello_long) 92 | { 93 | if (HELLO_G(direction)) { 94 | HELLO_G(counter)++; 95 | } else { 96 | HELLO_G(counter)--; 97 | } 98 | 99 | RETURN_LONG(HELLO_G(counter)); 100 | } 101 | 102 | PHP_FUNCTION(hello_double) 103 | { 104 | RETURN_DOUBLE(3.1415926535); 105 | } 106 | 107 | PHP_FUNCTION(hello_bool) 108 | { 109 | RETURN_BOOL(1); 110 | } 111 | 112 | PHP_FUNCTION(hello_null) 113 | { 114 | RETURN_NULL(); 115 | } 116 | 117 | PHP_FUNCTION(hello_greetme) 118 | { 119 | zval *zname; 120 | 121 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { 122 | RETURN_NULL(); 123 | } 124 | 125 | convert_to_string(zname); 126 | php_printf("Hello "); 127 | PHPWRITE(Z_STRVAL_P(zname), Z_STRLEN_P(zname)); 128 | php_printf("\n"); 129 | 130 | RETURN_TRUE; 131 | } 132 | 133 | PHP_FUNCTION(hello_add) 134 | { 135 | long a; 136 | double b; 137 | zend_bool return_long = 0; 138 | 139 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|b", &a, &b, &return_long) == FAILURE) { 140 | RETURN_NULL(); 141 | } 142 | 143 | if (return_long) { 144 | RETURN_LONG(a + b); 145 | } else { 146 | RETURN_DOUBLE(a + b); 147 | } 148 | } 149 | 150 | // Part 2 151 | 152 | PHP_FUNCTION(hello_array) 153 | { 154 | char *mystr; 155 | zval *mysubarray; 156 | 157 | array_init(return_value); 158 | 159 | add_index_long(return_value, 42, 123); 160 | 161 | add_next_index_string(return_value, "I should now be found at index 43", 1); 162 | 163 | add_next_index_stringl(return_value, "I'm at 44!", 10, 1); 164 | 165 | mystr = estrdup("Forty Five"); 166 | add_next_index_string(return_value, mystr, 0); 167 | 168 | add_assoc_double(return_value, "pi", 3.1415926535); 169 | 170 | ALLOC_INIT_ZVAL(mysubarray); 171 | array_init(mysubarray); 172 | add_next_index_string(mysubarray, "hello", 1); 173 | add_assoc_zval(return_value, "subarray", mysubarray); 174 | } 175 | 176 | PHP_FUNCTION(hello_array_strings) 177 | { 178 | zval *arr, **data; 179 | HashTable *arr_hash; 180 | HashPosition pointer; 181 | int array_count; 182 | 183 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) { 184 | RETURN_NULL(); 185 | } 186 | 187 | arr_hash = Z_ARRVAL_P(arr); 188 | array_count = zend_hash_num_elements(arr_hash); 189 | 190 | php_printf("The array passed contains %d elements\n", array_count); 191 | 192 | for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); 193 | zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS; 194 | zend_hash_move_forward_ex(arr_hash, &pointer)) { 195 | 196 | zval temp; 197 | char *key; 198 | int key_len; 199 | long index; 200 | 201 | if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) { 202 | PHPWRITE(key, key_len); 203 | } else { 204 | php_printf("%ld", index); 205 | } 206 | 207 | php_printf(" => "); 208 | 209 | temp = **data; 210 | zval_copy_ctor(&temp); 211 | convert_to_string(&temp); 212 | PHPWRITE(Z_STRVAL(temp), Z_STRLEN(temp)); 213 | php_printf("\n"); 214 | zval_dtor(&temp); 215 | 216 | } 217 | RETURN_TRUE; 218 | } 219 | 220 | PHP_FUNCTION(hello_get_global_var) 221 | { 222 | char *varname; 223 | int varname_len; 224 | zval **varvalue; 225 | 226 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &varname, &varname_len) == FAILURE) { 227 | RETURN_NULL(); 228 | } 229 | 230 | if (zend_hash_find(&EG(symbol_table), varname, varname_len + 1, (void**)&varvalue) == FAILURE) { 231 | php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Undefined variable: %s", varname); 232 | RETURN_NULL(); 233 | } 234 | 235 | *return_value = **varvalue; 236 | zval_copy_ctor(return_value); 237 | } 238 | 239 | PHP_FUNCTION(hello_set_local_var) 240 | { 241 | zval *newvar; 242 | char *varname; 243 | int varname_len; 244 | zval *value; 245 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &varname, &varname_len, &value) == FAILURE) { 246 | RETURN_NULL(); 247 | } 248 | 249 | ALLOC_INIT_ZVAL(newvar); 250 | *newvar = *value; 251 | zval_copy_ctor(newvar); 252 | zend_hash_add(EG(active_symbol_table), varname, varname_len + 1, &newvar, sizeof(zval*), NULL); 253 | 254 | RETURN_TRUE; 255 | } 256 | 257 | // Part 3 258 | 259 | PHP_FUNCTION(hello_person_new) 260 | { 261 | php_hello_person *person; 262 | char *name; 263 | int name_len; 264 | long age; 265 | 266 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) { 267 | RETURN_FALSE; 268 | } 269 | 270 | if (name_len < 1) { 271 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "No name given, person resource not created.", age); 272 | RETURN_FALSE; 273 | } 274 | 275 | if (age < 0 || age > 255) { 276 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Nonsense age (%d) given, person resource not created.", age); 277 | RETURN_FALSE; 278 | } 279 | 280 | person = emalloc(sizeof(php_hello_person)); 281 | person->name = estrndup(name, name_len); 282 | person->name_len = name_len; 283 | person->age = age; 284 | 285 | ZEND_REGISTER_RESOURCE(return_value, person, le_hello_person); 286 | } 287 | 288 | PHP_FUNCTION(hello_person_greet) 289 | { 290 | php_hello_person *person; 291 | zval *zperson; 292 | 293 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zperson) == FAILURE) { 294 | RETURN_FALSE; 295 | } 296 | 297 | ZEND_FETCH_RESOURCE(person, php_hello_person*, &zperson, -1, 298 | PHP_HELLO_PERSON_RES_NAME, le_hello_person); 299 | 300 | php_printf("Hello "); 301 | PHPWRITE(person->name, person->name_len); 302 | php_printf("!\nAccording to my records, you are %d years old.\n", person->age); 303 | 304 | RETURN_TRUE; 305 | } 306 | 307 | -------------------------------------------------------------------------------- /php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | error_reporting = E_ALL 4 | extension=modules/hello.so 5 | 6 | hello.greeting=Gettings World 7 | hello.direction=1 8 | -------------------------------------------------------------------------------- /php_hello.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_HELLO_H 2 | #define PHP_HELLO_H 1 3 | 4 | #ifdef ZTS 5 | #include "TSRM.h" 6 | #endif 7 | 8 | ZEND_BEGIN_MODULE_GLOBALS(hello) 9 | long counter; 10 | zend_bool direction; 11 | ZEND_END_MODULE_GLOBALS(hello) 12 | 13 | #ifdef ZTS 14 | #define HELLO_G(v) TSRMG(hello_globals_id, zend_hello_globals *, v) 15 | #else 16 | #define HELLO_G(v) (hello_globals.v) 17 | #endif 18 | 19 | #define PHP_HELLO_WORLD_VERSION "1.0" 20 | #define PHP_HELLO_WORLD_EXTNAME "hello" 21 | 22 | typedef struct _php_hello_person { 23 | char *name; 24 | int name_len; 25 | long age; 26 | } php_hello_person; 27 | 28 | #define PHP_HELLO_PERSON_RES_NAME "Person Data" 29 | 30 | PHP_MINIT_FUNCTION(hello); 31 | PHP_MSHUTDOWN_FUNCTION(hello); 32 | PHP_RINIT_FUNCTION(hello); 33 | 34 | PHP_FUNCTION(hello_world); 35 | PHP_FUNCTION(hello_long); 36 | PHP_FUNCTION(hello_double); 37 | PHP_FUNCTION(hello_bool); 38 | PHP_FUNCTION(hello_null); 39 | PHP_FUNCTION(hello_greetme); 40 | PHP_FUNCTION(hello_add); 41 | // Part 2 42 | PHP_FUNCTION(hello_array); 43 | PHP_FUNCTION(hello_array_strings); 44 | PHP_FUNCTION(hello_get_global_var); 45 | PHP_FUNCTION(hello_set_local_var); 46 | // Part 3 47 | PHP_FUNCTION(hello_person_new); 48 | PHP_FUNCTION(hello_person_greet); 49 | 50 | extern zend_module_entry hello_module_entry; 51 | #define phpext_hello_prt &hello_module_entry 52 | 53 | #endif 54 | --------------------------------------------------------------------------------