Jump to content

daeken

Members
  • Posts

    22
  • Joined

  • Last visited

    Never

Everything posted by daeken

  1. This _could_ be done... however, this would mean you couldn't let PHP access them directly, like an object. If it's just for internal use, go for it, otherwise I'd stick with normal objects. Happy Hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  2. First, I suggest you not use AOLbonics like '4' in place of 'for' and others as laziness is one of the attributes a programmer can _not_ afford to have. Second, don't use caps, it's offensive and your question is _not_ that important. Third, there are many entries on the php-dev mailing list about the basics of extension building for windows, and my ext_skel replacement will help you quite a bit. Happy Hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  3. I recently was pointed to the Amygdala spiking neural network library http://amygdala.sf.net/ for some AI stuff I was doing. I decided that PHP deserved to have an extension for this great C++ library, so I started working on it. I'm using my ext_skel replacement to ease the development, and that's nice so far (adding C++ support and class parameters, and I'll release it when I'm done, of course), but I've hit quite the brick wall... you create an instance of the LayerConstants class and set the parameters for the first layer, then create it and add it to the network, then you set the parameters in the LayerConstants object for the next layer, and so on and so forth. The problem is, I have no idea how I should keep track of what LayerConstants object I should be looking at, or how to get it from userspace. Perhaps I could just make any changes to the PHP instance of the LayerConstants change an instance of the C++ object somewhere in my code, if so, is there a way to have a function called when a parameter is changed in an extension (similar to __set() in normal PHP code)? Looking forward to any advise on the subject. Cheers, Lord Daeken M. BlackBlade (Cody Brocious)
  4. If you\'re processing the code, you should have absolutely no problem identifying code blocks... if you can\'t do that, then you really need to think about the way your processor works.
  5. I\'ve played with it a bit and haven\'t had any issues (except with thread safety). If you post your code here, i may be able to help you find the problem
  6. I\'ve come up with a replacement for ext_skel, based upon my code generator. It generates the header, C source, and config.m4 for you, with or without function definitions. --Edit-- Put up the new code which supports resources, constants, and classes! --Edit-- #!/usr/local/bin/php <?php function Gen($file, $extname) { $defs = array(); $res = array(); $const = array(); foreach($file as $line) { $parts = explode(\' \', trim($line)); $arr = array(); if(!preg_match(\'/^[s]*(#([^s]+)[s]+([^s]+)[s]+(.*)$|(void|int|float|double|bool|resource|array|object|mixed)[s]+([^:]*::)?([^(]+)(([^)]*));[s]*(.*))$/\', trim($line), $matches)) continue; if(!empty($matches[1]) && $matches[1][0] == \'#\') { if($matches[2] == \'resource\') $res[$matches[3]] = $matches[4]; elseif($matches[2] == \'define\') $const[$matches[3]] = $matches[4]; continue; } $arr[\'return\'] = $matches[5]; $arr[\'class\'] = substr($matches[6], 0, -2); $arr[\'name\'] = $matches[7]; $arr[\'params\'] = array(); $arr[\'desc\'] = $matches[9]; $last = 0; $opt = false; preg_match_all(\'/([|])?[s]*(.+?)[s]+$([^s[],=]+)[s]*=?[s]*([^s[]]*)[s]*([|])*,?[s]*/\', $matches[8], $matches); for($i = 0; $i < count($matches[0]); ++$i) { $type = $matches[2][$i]; $name = $matches[3][$i]; $def = $matches[4][$i]; if($matches[1][$i] == \'[\') $opt = $tempopt = true; elseif($matches[5][$i] == \'[\') $tempopt = true; elseif($matches[5][$i] == \']\' || empty($matches[5][$i])) $tempopt = false; $arr[\'params\'][$name] = array($type, $opt, $def); $opt = $tempopt; } $defs[] = $arr; } ob_start(); foreach($defs as $arr) { echo \'PHP_FUNCTION(\', $arr[\'name\']; if(!empty($arr[\'class\'])) echo \'_\'; echo \');\', NL; } $def = ob_get_contents(); ob_end_clean(); ob_start(); $objs = array(); foreach($defs as $arr) { if(!isset($objs[$arr[\'class\']])) $objs[$arr[\'class\']] = array(); $objs[$arr[\'class\']][] = $arr[\'name\']; } $minit = (string) null; foreach($res as $name => $text) { echo \'static int le_\', $name, \'_res;\', NL, \'static void _free_foobar_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)\', NL, \'{\', NL, \'}\', NL, NL; $minit .= \' le_\' . $name . \'_res = zend_register_list_destructors_ex(_free_\' . $name . \'_result, NULL, \' . $text . \', module_number);\' . NL; } foreach($const as $name => $val) { if($val[0] == \'"\') $type = \'STRING\'; elseif(strstr($val, \'.\')) $type = \'DOUBLE\'; else $type = \'LONG\'; $minit .= \' REGISTER_\' . $type . \'_CONSTANT("\' . $name . \'", \' . $val . \', CONST_CS | CONST_PERSISTENT);\' . NL; } echo NL; foreach($objs as $class => $funcs) { if(empty($class)) echo \'function_entry \', $extname, \'_functions[] = {\', NL; else { echo \'zend_class_entry \', $class, \'_class_entry;\', NL; echo \'function_entry \', $class, \'_class_functions[] = {\', NL; $minit .= \' INIT_CLASS_ENTRY(\' . $class . \'_class_entry, "\' . $class . \'", \' . $class . \'_class_functions);\' . NL . \' zend_register_internal_class(&\' . $class . \'_class_entry TSRMLS_CC);\' . NL; } foreach($funcs as $func) { if(empty($class)) echo \' ZEND_FE(\', $func, \', NULL)\', NL; else echo \' ZEND_FALIAS(\', $func, \', \', $func, \'_, NULL)\', NL; } echo \' {NULL, NULL, NULL}\', NL, \'};\', NL, NL, NL; } if(!isset($objs[\'\'])) echo \'function_entry \', $extname, \'_functions[] = {\', NL, \' {NULL, NULL, NULL}\', NL, \'};\', NL, NL, NL; $entry = ob_get_contents(); ob_end_clean(); ob_start(); foreach($defs as $arr) { echo \'/* {{{ proto \', $arr[\'return\'], \' \'; if(!empty($arr[\'class\'])) echo $arr[\'class\'], \'::\'; echo $arr[\'name\'], \'(\'; $i = 0; $optcount = 0; foreach($arr[\'params\'] as $name => $temp) { list($type, $opt, $default) = $temp; if(!$opt) { echo str_repeat(\']\', $optcount); $optcount = 0; } if($opt) { if($i != 0) echo \' \'; echo \'[\'; ++$optcount; } if(++$i > 1) echo \', \'; echo $type, \' \', $name; if($opt && !empty($default)) echo \' = \', $default; } echo str_repeat(\']\', $optcount); echo \')\', NL, \' \', $arr[\'desc\'], \' */\', NL, \'PHP_FUNCTION(\', $arr[\'name\']; if(!empty($arr[\'class\'])) echo \'_\'; echo \')\', NL, \'{\', NL; $format = (string) null; $params = (string) null; $i = 0; foreach($arr[\'params\'] as $name => $temp) { list($type, $opt, $default) = $temp; switch($type) { case \'int\': echo \' int \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = 0\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'l\'; $params .= \'&\' . $name; break; case \'string\': echo \' char *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL, \' int \', $name, \'_len\'; if($opt && !empty($default)) echo \' = \', strlen($default) - 2; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'s\'; $params .= \'&\' . $name . \', &\' . $name . \'_len\'; break; case \'bool\': case \'boolean\': echo \' zend_bool \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = FALSE\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'b\'; $params .= \'&\' . $name; break; case \'array\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'a\'; $params .= \'&\' . $name; break; case \'mixed\': case \'resource\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'z\'; $params .= \'&\' . $name; break; case \'object\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'o\'; $params .= \'&\' . $name; break; case \'double\': case \'float\': echo \' double \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = 0\'; echo \';\', NL; if($opt) $format .= \'|\'; $format .= \'d\'; $params .= \'&\' . $name; break; } if(++$i != count($arr[\'params\'])) $params .= \', \'; } $need = 0; foreach($arr[\'params\'] as $name => $temp) { if(!$temp[1]) ++$need; } if(count($arr[\'params\']) > 0) echo \' if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "\', $format, \'", \', $params, \') == FAILURE)\', NL, \' return;\', NL, \'}\', NL, NL; else echo \'}\', NL, \'/* }}} */\', NL, NL; } $funcs = ob_get_contents(); ob_end_clean(); return array($def, $entry, $funcs, $minit); } function Get() { return trim(fgets(STDIN)); } define(\'NL\', chr(10)); echo \'Welcome to the extension builder.\', NL, \'To get started, type the name of your extension.\', NL; $ext = Get(); $foo = false; echo \'Ok. To get started with making extension `\', $ext, \'\' we will make the directory.\', NL; while(!$foo) { echo \'Please give the path to the ext/ directory of the PHP source tree.\', NL; $dir = Get(); $foo = is_dir($dir); } @mkdir($dir . \'/\' . $ext); echo \'Extension directory created.\', NL, \'What is your name?\', NL; $author = str_pad(Get(), 61, \' \', STR_PAD_RIGHT); echo \'What libraries (if any) are needed by this extension? (space-seperated only please)\', NL; $libs = explode(\' \', Get()); echo \'What includes (if any) are needed by this extension? (space-seperated only please)\', NL; $incs = explode(\' \', Get()); while(true) { echo \'What is the filename of your function definition file? (leave blank if you don\'t have one)\', NL; $def = Get(); if(empty($def)) { $file = array(); break; } if(!empty($def) && !file_exists($def)) echo \'File does not exist.\', NL; else { $file = file($def); break; } } while(true) { echo \'Do you want --with-\', $ext, \' or --enable-\', $ext, \' ? (Enter either with or enable)\', NL; $flag = strtolower(Get()); if($flag == \'with\' || $flag == \'enable\') break; } $head = fopen($dir . \'/\' . $ext . \'/php_\' . $ext . \'.h\', \'w\'); ob_start(); echo \'/*\', NL, \' +----------------------------------------------------------------------+\', NL, \' | PHP Version 4 |\', NL, \' +----------------------------------------------------------------------+\', NL, \' | Copyright (c) 1997-2003 The PHP Group |\', NL, \' +----------------------------------------------------------------------+\', NL, \' | This source file is subject to version 2.02 of the PHP license, |\', NL, \' | that is bundled with this package in the file LICENSE, and is |\', NL, \' | available at through the world-wide-web at |\', NL, \' | http://www.php.net/license/2_02.txt. |\', NL, \' | If you did not receive a copy of the PHP license and are unable to |\', NL, \' | obtain it through the world-wide-web, please send a note to |\', NL, \' | license@php.net so we can mail you a copy immediately. |\', NL, \' +----------------------------------------------------------------------+\', NL, \' | Author: \', $author, \'|\', NL, \' +----------------------------------------------------------------------+\', NL, \' $Id: header,v 1.10.8.1 2003/07/14 15:59:18 sniper Exp $ \', NL, \'*/\', NL, NL; $fileheader = ob_get_contents(); ob_end_clean(); $h = \'#ifndef PHP_\' . strtoupper($ext) . \'_H #define PHP_\' . strtoupper($ext) . \'_H extern zend_module_entry \' . $ext . \'_module_entry; #define phpext_\' . $ext . \'_ptr &\' . $ext . \'_module_entry #ifdef PHP_WIN32 #define PHP_\' . strtoupper($ext) . \'_API __declspec(dllexport) #else #define PHP_\' . strtoupper($ext) . \'_API #endif #ifdef ZTS #include "TSRM.h" #endif \' . NL; foreach($incs as $include) if(!empty($include)) $h .= \'#include <\' . $include . \'>\' . NL; $h .= NL . \'PHP_MINIT_FUNCTION(\' . $ext . \'); PHP_MSHUTDOWN_FUNCTION(\' . $ext . \'); PHP_RINIT_FUNCTION(\' . $ext . \'); PHP_RSHUTDOWN_FUNCTION(\' . $ext . \'); PHP_MINFO_FUNCTION(\' . $ext . \');\' . NL . NL; fwrite($head, $fileheader); fwrite($head, $h); list($defs, $entry, $funcs, $minit) = Gen($file, $ext); fwrite($head, $defs); fwrite($head, \'#endif\' . NL); fclose($head); $source = fopen($dir . \'/\' . $ext . \'/\' . $ext . \'.c\', \'w\'); fwrite($source, $fileheader); $c = \'#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_\' . $ext . \'.h" /* True global resources - no need for thread safety here */ static int le_\' . $ext . \';\' . NL . NL; fwrite($source, $c); fwrite($source, $entry); $c = \'/* {{{ \' . $ext . \'_module_entry */ zend_module_entry \' . $ext . \'_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "\' . $ext . \'", \' . $ext . \'_functions, PHP_MINIT(\' . $ext . \'), PHP_MSHUTDOWN(\' . $ext . \'), PHP_RINIT(\' . $ext . \'), /* Replace with NULL if there\'s nothing to do at request start */ PHP_RSHUTDOWN(\' . $ext . \'), /* Replace with NULL if there\'s nothing to do at request end */ PHP_MINFO(\' . $ext . \'), #if ZEND_MODULE_API_NO >= 20010901 "0.1", /* Replace with version number for your extension */ #endif STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_\' . strtoupper($ext) . \' ZEND_GET_MODULE(\' . $ext . \') #endif /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(\' . $ext . \') { \' . $minit . \' return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(\' . $ext . \') { return SUCCESS; } /* }}} */ /* Remove if there\'s nothing to do at request start */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(\' . $ext . \') { return SUCCESS; } /* }}} */ /* Remove if there\'s nothing to do at request end */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(\' . $ext . \') { return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(\' . $ext . \') { php_info_print_table_start(); php_info_print_table_header(2, "\' . $ext . \' support", "enabled"); php_info_print_table_end(); } /* }}} */\' . NL . NL; fwrite($source, $c); fwrite($source, $funcs); fclose($source); $m4 = fopen($dir . \'/\' . $ext . \'/config.m4\', \'w\'); if($flag == \'enable\') fwrite($m4, \'PHP_ARG_ENABLE(\' . $ext . \', for \' . $ext . \' support,\' . NL . \'[ --enable-\' . $ext . \' Enable \' . $ext . \' support])\' . NL); else fwrite($m4, \'PHP_ARG_WITH(\' . $ext . \', for \' . $ext . \' support,\' . NL . \'[ --with-\' . $ext . \' Include \' . $ext . \' support])\' . NL); fwrite($m4, \'if test "$PHP_\' . strtoupper($ext) . \'" != "no"; then\' . NL); foreach($libs as $lib) { if(!empty($lib)) fwrite($m4, \' PHP_CHECK_LIBRARY(\' . $lib . \',\' . $lib . \',\' . NL . \' [\' . NL . \' AC_DEFINE(HAVE_\' . strtoupper($ext) . \'LIB,1,[ ])\' . NL . \' ],[\' . NL . \' AC_MSG_ERROR([wrong \' . $lib . \' lib version of lib not found])\' . NL . \' ],[\' . NL . \' -l\' . $lib . NL . \' ])\' . NL . \' PHP_ADD_LIBRARY_WITH_PATH(\' . $ext . \', /usr/lib, \' . strtoupper($ext) . \'_SHARED_LIBADD)\' . NL); } fwrite($m4, \' PHP_NEW_EXTENSION(\' . $ext . \', \' . $ext . \'.c, $ext_shared)\' . NL . \'fi\' . NL); fclose($m4); ?> Example definition file: void SomeClass::Foo(int $bar); Description! #define foo "bar" #resource foobar "Foobar Resource" Have fun! Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  7. New version, new parser, and a new feature: optional parameters. #!/usr/local/bin/php <?php if($_SERVER[\'argc\'] < 3) { echo \'Usage: \', $_SERVER[\'argv\'][0], \' <extension name> <definition>\', chr(10); exit; } $file = file($_SERVER[\'argv\'][2]); $defs = array(); foreach($file as $line) { $parts = explode(\' \', trim($line)); $arr = array(); $arr[\'return\'] = $parts[0]; $arr[\'name\'] = substr($parts[1], 0, strpos($parts[1], \'(\')); $arr[\'params\'] = array(); $arr[\'desc\'] = trim(substr($line, strpos($line, \';\') + 1)); $pos = strpos($line, \'(\') + 1; $line = trim(substr($line, $pos, strrpos($line, \')\') - $pos)); $last = 0; $opt = false; preg_match_all(\'/([|])?[s]*(.+?)[s]+$([^s[],=]+)[s]*=?[s]*([^s[]]*)[s]*([|])*,?[s]*/\', $line, $matches); for($i = 0; $i < count($matches[0]); ++$i) { $type = $matches[2][$i]; $name = $matches[3][$i]; $def = $matches[4][$i]; if($matches[1][$i] == \'[\') $opt = $tempopt = true; elseif($matches[5][$i] == \'[\') $tempopt = true; elseif($matches[5][$i] == \']\' || empty($matches[5][$i])) $tempopt = false; $arr[\'params\'][$name] = array($type, $opt, $def); $opt = $tempopt; } $defs[] = $arr; } echo \'function_entry \', $_SERVER[\'argv\'][1], \'_functions[] = {\', chr(10); foreach($defs as $arr) echo \' ZEND_FE(\', $arr[\'name\'], \', NULL)\', chr(10); echo \' {NULL, NULL, NULL}\', chr(10), \'};\', chr(10), chr(10), chr(10); foreach($defs as $arr) { echo \'/* {{{ proto \', $arr[\'return\'], \' \', $arr[\'name\'], \'(\'; $i = 0; $optcount = 0; foreach($arr[\'params\'] as $name => $temp) { list($type, $opt, $default) = $temp; if(!$opt) { echo str_repeat(\']\', $optcount); $optcount = 0; } if($opt) { if($i != 0) echo \' \'; echo \'[\'; ++$optcount; } if(++$i > 1) echo \', \'; echo $type, \' \', $name; if($opt && !empty($default)) echo \' = \', $default; } echo str_repeat(\']\', $optcount); echo \')\', chr(10), \' \', $arr[\'desc\'], \' */\', chr(10), \'PHP_FUNCTION(\', $arr[\'name\'], \')\', chr(10), \'{\', chr(10); $format = (string) null; $params = (string) null; $i = 0; foreach($arr[\'params\'] as $name => $temp) { list($type, $opt, $default) = $temp; switch($type) { case \'int\': echo \' int \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = 0\'; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'l\'; $params .= \'&\' . $name; break; case \'string\': echo \' char *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', chr(10), \' int \', $name, \'_len\'; if($opt && !empty($default)) echo \' = \', strlen($default) - 2; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'s\'; $params .= \'&\' . $name . \', &\' . $name . \'_len\'; break; case \'bool\': case \'boolean\': echo \' zend_bool \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = FALSE\'; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'b\'; $params .= \'&\' . $name; break; case \'array\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'a\'; $params .= \'&\' . $name; break; case \'mixed\': case \'resource\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'z\'; $params .= \'&\' . $name; break; case \'object\': echo \' zval *\', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = NULL\'; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'o\'; $params .= \'&\' . $name; break; case \'double\': case \'float\': echo \' double \', $name; if($opt && !empty($default)) echo \' = \', $default; elseif($opt) echo \' = 0\'; echo \';\', chr(10); if($opt) $format .= \'|\'; $format .= \'d\'; $params .= \'&\' . $name; break; } if(++$i != count($arr[\'params\'])) $params .= \', \'; } $need = 0; foreach($arr[\'params\'] as $name => $temp) { if(!$temp[1]) ++$need; } echo \' if(ZEND_NUM_ARGS() < \', $need, \') WRONG_PARAM_COUNT;\', chr(10), \' if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "\', $format, \'", \', $params, \') == FAILURE)\', chr(10), \' return;\', chr(10), \'}\', chr(10), chr(10); } ?> Example definition: int foo(string $bar[, int $bleh]); Simple function! bool is_even([mixed $var = 5]); Checks if a variable is even. Output: function_entry openal_functions[] = { ZEND_FE(foo, NULL) ZEND_FE(is_even, NULL) {NULL, NULL, NULL} }; /* {{{ proto int foo(string bar [, int bleh]) Simple function! */ PHP_FUNCTION(foo) { char *bar; int bar_len; int bleh = 0; if(ZEND_NUM_ARGS() < 1) WRONG_PARAM_COUNT; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &bar, &bar_len, &bleh) == FAILURE) return; } /* {{{ proto bool is_even([mixed var = 5]) Checks if a variable is even. */ PHP_FUNCTION(is_even) { zval *var = 5; if(ZEND_NUM_ARGS() < 0) WRONG_PARAM_COUNT; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &var) == FAILURE) return; } Have fun! Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  8. Well, after about half an hour of work, I have a full rewrite of my skeleton generator. This time, instead of a C header file, you create a function definition file. Example: int foo(string $bar, int $bleh); Simple function! bool is_even(mixed $var); Checks if a variable is even. Another notable difference is that it generates full documentation in the C code, and parses parameters. Example output of that above definition file is: function_entry openal_functions[] = { ZEND_FE(foo, NULL) ZEND_FE(is_even, NULL) {NULL, NULL, NULL} }; /* {{{ proto int foo(string bar, int bleh) Simple function! */ PHP_FUNCTION(foo) { char *bar; int bar_len; int bleh; if(ZEND_NUM_ARGS() < 2) WRONG_PARAM_COUNT; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &bar, &bar_len, &bleh) == FAILURE) return; } /* {{{ proto bool is_even(mixed var) Checks if a variable is even. */ PHP_FUNCTION(is_even) { zval *var; if(ZEND_NUM_ARGS() < 1) WRONG_PARAM_COUNT; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &var) == FAILURE) return; } As you can see, this does all the really hard work for you, leading to more efficient extension building And now for the code... [php:1:7617edc449] #!/usr/local/bin/php <?php if($_SERVER[\'argc\'] < 3) { echo \'Usage: \', $_SERVER[\'argv\'][0], \' <extension name> <definition>\', chr(10); exit; } $file = file($_SERVER[\'argv\'][2]); $defs = array(); foreach($file as $line) { $parts = explode(\' \', trim($line)); $arr = array(); $arr[\'return\'] = $parts[0]; $arr[\'name\'] = substr($parts[1], 0, strpos($parts[1], \'(\')); $arr[\'params\'] = array(); $arr[\'desc\'] = trim(substr($line, strpos($line, \';\') + 1)); $pos = strpos($line, \'(\') + 1; $line = substr($line, $pos, strrpos($line, \')\') - $pos); $params = explode(\',\', $line); foreach($params as $part) { list($type, $name) = explode(\' \', trim($part)); $arr[\'params\'][str_replace(\'$\', (string) null, $name)] = $type; } $defs[] = $arr; } echo \'function_entry \', $_SERVER[\'argv\'][1], \'_functions[] = {\', chr(10); foreach($defs as $arr) echo \' ZEND_FE(\', $arr[\'name\'], \', NULL)\', chr(10); echo \' {NULL, NULL, NULL}\', chr(10), \'};\', chr(10), chr(10), chr(10); foreach($defs as $arr) { echo \'/* {{{ proto \', $arr[\'return\'], \' \', $arr[\'name\'], \'(\'; $i = 0; foreach($arr[\'params\'] as $name => $type) { echo $type, \' \', $name; if(++$i != count($arr[\'params\'])) echo \', \'; } echo \')\', chr(10), \' \', $arr[\'desc\'], \' */\', chr(10), \'PHP_FUNCTION(\', $arr[\'name\'], \')\', chr(10), \'{\', chr(10); $format = (string) null; $params = (string) null; $i = 0; foreach($arr[\'params\'] as $name => $type) { switch($type) { case \'int\': echo \' int \', $name, \';\', chr(10); $format .= \'l\'; $params .= \'&\' . $name; break; case \'string\': echo \' char *\', $name, \';\', chr(10), \' int \', $name, \'_len;\', chr(10); $format .= \'s\'; $params .= \'&\' . $name . \', &\' . $name . \'_len\'; break; case \'bool\': case \'boolean\': echo \' zend_bool \', $name, \';\', chr(10); $format .= \'b\'; $params .= \'&\' . $name; break; case \'array\': echo \' zval *\', $name, \';\', chr(10); $format .= \'a\'; $params .= \'&\' . $name; break; case \'mixed\': case \'resource\': echo \' zval *\', $name, \';\', chr(10); $format .= \'z\'; $params .= \'&\' . $name; break; case \'object\': echo \' zval *\', $name, \';\', chr(10); $format .= \'o\'; $params .= \'&\' . $name; break; case \'double\': case \'float\': echo \' double \', $name, \';\', chr(10); $format .= \'d\'; $params .= \'&\' . $name; break; } if(++$i != count($arr[\'params\'])) $params .= \', \'; } echo \' if(ZEND_NUM_ARGS() < \', count($arr[\'params\']), \') WRONG_PARAM_COUNT;\', chr(10), \' if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \"\', $format, \'\", \', $params, \') == FAILURE)\', chr(10), \' return;\', chr(10), \'}\', chr(10), chr(10); } ?> [/php:1:7617edc449] Have fun Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  9. Just an example header file and the skeleton code generated: /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Cody Brocious | +----------------------------------------------------------------------+ $Id: header,v 1.10.8.1 2003/07/14 15:59:18 sniper Exp $ */ #ifndef PHP_OPENAL_H #define PHP_OPENAL_H extern zend_module_entry openal_module_entry; #define phpext_openal_ptr &openal_module_entry #ifdef PHP_WIN32 #define PHP_OPENAL_API __declspec(dllexport) #else #define PHP_OPENAL_API #endif #ifdef ZTS #include "TSRM.h" #endif #include <AL/al.h> PHP_MINIT_FUNCTION(openal); PHP_MSHUTDOWN_FUNCTION(openal); PHP_RINIT_FUNCTION(openal); PHP_RSHUTDOWN_FUNCTION(openal); PHP_MINFO_FUNCTION(openal); PHP_FUNCTION(alEnable); PHP_FUNCTION(alDisable); PHP_FUNCTION(alIsEnabled); PHP_FUNCTION(alHint); PHP_FUNCTION(alGetBooleanv); PHP_FUNCTION(alGetIntegerv); #ifdef ZTS #define OPENAL_G(v) TSRMG(openal_globals_id, zend_openal_globals *, v) #else #define OPENAL_G(v) (openal_globals.v) #endif #endif /* PHP_OPENAL_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * indent-tabs-mode: t * End: */ Skeleton Code: function_entry openal_functions[] = { ZEND_FE(alEnable, NULL) ZEND_FE(alDisable, NULL) ZEND_FE(alIsEnabled, NULL) ZEND_FE(alHint, NULL) ZEND_FE(alGetBooleanv, NULL) ZEND_FE(alGetIntegerv, NULL) {NULL, NULL, NULL} }; /* {{{ proto void alEnable() DESCRIPTION */ PHP_FUNCTION(alEnable) { } /* }}} */ /* {{{ proto void alDisable() DESCRIPTION */ PHP_FUNCTION(alDisable) { } /* }}} */ /* {{{ proto void alIsEnabled() DESCRIPTION */ PHP_FUNCTION(alIsEnabled) { } /* }}} */ /* {{{ proto void alHint() DESCRIPTION */ PHP_FUNCTION(alHint) { } /* }}} */ /* {{{ proto void alGetBooleanv() DESCRIPTION */ PHP_FUNCTION(alGetBooleanv) { } /* }}} */ /* {{{ proto void alGetIntegerv() DESCRIPTION */ PHP_FUNCTION(alGetIntegerv) { } /* }}} */
  10. I was whipping up a quick OpenAL extension, so I started by writing the php_openal.h file and adding the appropriate PHP_FUNCTION(...); lines... well, soon after I got the idea of taking that header file and generating base code for the extension itself from it. Here\'s what I ended up with: [php:1:88128bd8ea] #!/usr/local/bin/php <?php if($_SERVER[\'argc\'] < 3) { echo \'Usage: \', $_SERVER[\'argv\'][0], \' <extension name> <header file>\', chr(10); exit; } $file = file($_SERVER[\'argv\'][2]); $funcs = array(); foreach($file as $line) { $line = trim($line); if(substr($line, 0, 13) == \'PHP_FUNCTION(\') $funcs[] = substr($line, 13, -2); } echo \'function_entry \', $_SERVER[\'argv\'][1], \'_functions[] = {\', chr(10); foreach($funcs as $foo) echo \' ZEND_FE(\', $foo, \', NULL)\', chr(10); echo \' {NULL, NULL, NULL}\', chr(10), \'};\', chr(10), chr(10), chr(10); foreach($funcs as $foo) echo \'/* {{{ proto void \', $foo, \'()\', chr(10), \' DESCRIPTION */\', chr(10), chr(10), \'PHP_FUNCTION(\', $foo, \')\', chr(10), \'{\', chr(10), \'}\', chr(10), \'/* }}} */\', chr(10), chr(10); ?> [/php:1:88128bd8ea] Have fun with it, and as always Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  11. I must note that you can develop PHP extensions on non-linux platforms, although documentation on doing so is sparse for the most part. My guide series is covering all platforms that PHP will run on Happy Hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  12. Welcome! Perhaps the manual would be helpful, as it explains basic core hacking quite well (although everything after that is explained very very poorly). Check it out at http://phpfreaks.com/phpmanual/page/zend.html . Happy hacking, Daeken M. BlackBlade (Cody Brocious)
  13. daeken

    Smarty++

    hmm... perhaps i will later today.
  14. Hopefully we get to the bottom of this, as future upgrades of the manual on PHPfreaks may remove the last traces of our (much needed) PHP4 extension docs.
  15. Ok... the documentation on call_user_function_ex() in the manual (if it\'s still there) is outdated and incomplete... here\'s my version. ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_seperation, HashTable *symbol_table TSRMLS_DC); function_table is the hash table where the function you wish to call is located. If you\'re using object_pp, set this to NULL. If the function is global, most likely it\'s located in the hash table returned by the macro CG() with the parameter `function_table\', i.e. CG(function_table) . object_pp is a pointer to a zval pointer where an initialized object is located. If you use this, set function_table to NULL, as previously noted. function_name is a pointer to a zval which contains the name of the function in string form. retval_ptr_ptr is a pointer to a zval pointer which will contain the return value of the function. The zval passed doesn\'t need to be initialized, and it may cause problems if you initialize it when it\'s not neccesary. You must always pass a real pointer to a zval pointer, you may not use NULL for this as it will cause a segmentation fault. param_count is the number of parameters you wish to pass to the function being called. params is an array of pointers to zval pointers. Note: this is _not_ a PHP/zval array, it is a C array. Example: zval *foo; zval *bar; zval **params[2]; params[0] = &foo; params[1] = bar; no_seperation is either 1 or 0, 0 being no zval seperation, 1 enabling zval seperation. Anyone know what this is? I haven\'t been able to find out anywhere symbol_table is the hash table for symbols. I currently don\'t know what this is, so when I find out, I\'ll edit the post and put it here After the symbol_table parameter, you should put TSRMLS_CC to make it threadsafe. call_user_function_ex() returns FAILURE if it couldn\'t call the function, and SUCCESS if it could. Here\'s an example calling a global function with no parameters: PHP_FUNCTION(example_call_func) { zval *function; MAKE_STD_ZVAL(function); ZVAL_STRING(function, "example_usermode_function", 1); if(call_user_function_ex(CG(function_table), NULL, function, &return_value, 0, NULL, 0, NULL TSRMLS_CC) != FAILURE) return; else RETURN_FALSE; } Now the same example with 1 parameter being passed to the usermode function: PHP_FUNCTION(example_call_func) { zval *function, *num; zval **params[1]; // Creates array of parameters with 1 element allocated. MAKE_STD_ZVAL(function); MAKE_STD_ZVAL(num); ZVAL_STRING(function, "example_usermode_function", 1); ZVAL_LONG(num, 15); params[0] = num; // Makes num the first parameter to example_usermode_function(). if(call_user_function_ex(CG(function_table), NULL, function, &return_value, 1, params, 0, NULL TSRMLS_CC) != FAILURE) return; else RETURN_FALSE; } And now an example taking an object and method name as parameters and calling the method: PHP_FUNCTION(example_call_func) { zval *object, *method; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &object, &method) == FAILURE) { zend_error(E_WARNING, "You must pass an object and a method name to example_call_func"); return; } if(call_user_function_ex(NULL, &object, method, &return_value, 0, NULL, 0, NULL TSRMLS_CC) != FAILURE) return; else RETURN_FALSE; } Hopefully you found this useful. If you have any questions, feel free to post here and ask Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious)
  16. daeken

    Smarty++

    Even with caching, it\'s much much slower than Smarty++... that benchmark was with caching set up properly
  17. daeken

    Cool!

    agreed. no more clunky mailing-lists! *rips off his pants and goes streaking through the forums *
  18. A few months ago, I embarked on a project called Smarty++ (or Smartypp), it\'s a C-based (for now... may be going with C++ for future versions, simply because of the `string\' class) Smarty templating engine extension port. Currently only static text and variables are supported, no other tags or fancy stuff. To run a simple template 10000 times with standard Smarty, it takes 54 seconds on this box. With Smarty++, it took 9 seconds. This benchmark alone has satisfied me with my work so far, though i have much planned for the future. Hopefully you\'ll find the current version useful. I\'ve only tested in Debian and Gentoo GNU/Linux, but it should work on windows with few (if any) modifications. Current code is available here: http://eqmoders.com/smartypp.tar.bz2 . If you find/fix any bugs or add on, please post here about your findings! Happy hacking, Lord Daeken M. BlackBlade (Cody Brocious)
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.