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)