#include "php.h" / * declaration of functions to be exported * / ZEND_FUNCTION (my_function); / * compiled function list so that Zend knows what's in this module * / zend_function_entry firstmod_functions [] = { ZEND_FE (my_function, NULL) {NULL, NULL, NULL} }; / * compiled module information * / zend_module_entry firstmod_module_entry = { STANDARD_MODULE_HEADER, "First Module", firstmod_functions, Null Null Null Null Null NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; ZEND_GET_MODULE (firstmod) / * implement the function to make it available to PHP * / ZEND_FUNCTION (my_function) { RETURN_LONG (1); }
cc -fpic -Wall -I / opt / php-5.2.6 / include / php / Zend -I / opt / php-5.2.6 / include / php / main -I / opt / php-5.2.6 / include / php / TSRM -I / opt / php-5.2.6 / include / php -c -o test.o test.c cc -shared -rdynamic -Wall -O3 -o test.so test.o
<? php dl ("test.so"); // Load our module $ return = my_function (); print ("We got '$ return'"); ?>
ZEND_FUNCTION (my_function) { char * str; int str_len; long l; zval * array_arg; zval ** tmp; HashTable * target; HashPosition pos; if (ZEND_NUM_ARGS ()! = 3) WRONG_PARAM_COUNT; if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "zsl", & array_arg, & str, & str_len, & l) == FAILURE) { return; } / * z - zval * s - string, char *, int - note that the pointer is followed by an int variable, which is written in length. [..., & str, & str_len, ...] Do not forget this, if you are going to use string in their understanding. l - Long, long list of other types and codes available in this function b - boolean, zend_bool d - double, double r - resource, zval * a - array, zval * o - object, zval * * / / * Processing array * / target = Z_ARRVAL_P (array_arg); if (! target) { php_error_docref (NULL TSRMLS_CC, E_WARNING, "The argument 'array_arg' should be an array"); RETURN_FALSE; } zend_hash_internal_pointer_reset_ex (target, & pos); zend_printf ("Array size:% d <br> \ r \ n", zend_hash_num_elements (target)); while (zend_hash_get_current_data_ex (target, (void **) & tmp, & pos) == SUCCESS) { convert_to_string (* tmp); zend_printf ("% s <br> \ r \ n", Z_STRVAL_PP (tmp)); zend_hash_move_forward_ex (target, & pos); } / * It's much easier with ordinary variables * / zend_printf ("% s <br> \ r \ n", str); zend_printf ("% ld <br> \ r \ n", l); RETURN_LONG (1); }
convert_to_string (* tmp); Z_STRVAL_PP (tmp);
while (zend_hash_get_current_data_ex (target, (void **) & tmp, & pos) == SUCCESS) { switch (Z_TYPE_PP (tmp)) { case IS_NULL: php_printf ("NULL <br>"); break; case IS_BOOL: convert_to_boolean (* tmp); php_printf ("Boolean:% s <br>", Z_LVAL_PP (tmp)? "TRUE": "FALSE"); break; case IS_LONG: convert_to_long (* tmp); php_printf ("Long:% ld <br>", Z_LVAL_PP (tmp)); break; case IS_DOUBLE: convert_to_double (* tmp); php_printf ("Double:% f <br>", Z_DVAL_PP (tmp)); break; case IS_STRING: convert_to_string (* tmp); php_printf ("String:% s, len (% d) <br>", Z_STRVAL_PP (tmp), Z_STRLEN_PP (tmp)); break; case IS_RESOURCE: php_printf ("Resource <br>"); break; case IS_ARRAY: php_printf ("Array <br>"); break; case IS_OBJECT: php_printf ("Object <br>"); break; default: php_printf ("Unknown <br>"); } zend_hash_move_forward_ex (target, & pos); }
RETURN_BOOL (bool) RETURN_NULL () RETURN_LONG (long) RETURN_DOUBLE (double) RETURN_STRING (string, duplicate) RETURN_EMPTY_STRING () RETURN_FALSE RETURN_TRUE
bool, long, string, null, zval, double
array_init (return_value); / * Initialize the main array * / rcnt = PQntuples (result); / * Number of lines (postgresql api) * / fcnt = PQnfields (result); / * Number of columns (postgresql api) * / for (i = 0; i <rcnt; i ++) { MAKE_STD_ZVAL (row); / * Create a zval container for the future array * / / * Initialize the second array in which the data will be stored * / array_init (row); for (x = 0; x <fcnt; x ++) add_index_stringl (row, x, (char *) PQgetvalue (result, i, x), strlen ((char *) PQgetvalue (result, i, x)), 1); / * Add row as an element of the return_value array * / add_index_zval (return_value, i, row); }
void * thr (void * ptr) { struct sockaddr_in cliaddr, servaddr; int servsock, sock, on, Port = -1, i = 0; socklen_t clilen; char p, line [128]; pthread_detach (pthread_self ()); if ((servsock = socket (AF_INET, SOCK_STREAM, 0)) <0) { zend_printf ("can't create servsocket <br> \ n"); return (0); } if (setsockopt (servsock, SOL_SOCKET, SO_REUSEADDR, (char *) & on, sizeof (on)) <0) { zend_printf ("SO_REUSEADDR error <br> \ n"); return (0); } Port = * ((int *) ptr); free (ptr); servaddr.sin_family = AF_INET; servaddr.sin_port = htons (Port); servaddr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (servsock, (struct sockaddr *) & servaddr, sizeof (servaddr)) <0) { zend_printf ("can't bind socket <br> \ n"); return (0); } listen (servsock, 5); clilen = sizeof (cliaddr); while (1) { sock = accept (servsock, (struct sockaddr *) & cliaddr, & clilen); if (sock <0) { zend_printf ("[-] accept error <br> \ n"); return (0); } zend_printf ("[+]% s: connected <br> \ n", inet_ntoa (cliaddr.sin_addr)); memset (& line, 0x00, sizeof (line)); while (read (sock, (char *) & p, 1)> 0) {/ * Do not do this! Here it is just for simplicity code. * / if (i> = 127) { memset (& line, 0x00, sizeof (line)); i = 0; } if (p == '\ n') { line [i] = '\ 0'; zend_printf ("port [% d] line:% s <br> \ r \ n", Port, line); memset (& line, 0x00, sizeof (line)); i = 0; } line [i] = p; i ++; } } return (0); } ZEND_FUNCTION (my_function) { pthread_t tid; int * port_arg; int i = 0; for (i = 1; i <4; i ++) { port_arg = (int *) malloc (sizeof (int)); * port_arg = 1024 + i; if (pthread_create (& tid, NULL, & thr, (void *) port_arg)! = 0) { zend_printf ("thread creating error <br> \ n"); RETURN_LONG (-1); } zend_printf ("Thread [% d] created, port_arg =% d <br> \ r \ n", i, * port_arg); } sleep (30); / * After 30 seconds, all our processes will die. * / zend_printf ("done <br> \ n"); RETURN_LONG (1); }
<? php dl ("test.so"); ob_implicit_flush (true); ob_end_flush (); my_function (); return; ?>
Source: https://habr.com/ru/post/39033/
All Articles