I have a performance intensive routine that is written in PHP that I'd like to port to C++ for a performance increase. Is there any way to write a plugin or extension or something using C++ and interface with it from PHP? WITHOUT manually editing the actual PHP source?
Answers
After posting I came across CodeGen_PECL which creates a skeleton extension from an XML based description of the extension. This includes a tag make it output C++
As well as making sure the header file used extern "C", the generated cpp file also ensured the ZEND_GET_MODULE(hello) was inside an extern "C" block also.
As expected, the biggest difference was in the m4 file, which looked like this:
dnl
dnl $ Id: $
dnl
PHP_ARG_ENABLE(hello, whether to enable hello functions,
[ --enable-hello Enable hello support])
if test "$PHP_HELLO" != "no"; then
PHP_REQUIRE_CXX
AC_LANG_CPLUSPLUS
PHP_ADD_LIBRARY(stdc++,,HELLO_SHARED_LIBADD)
export OLD_CPPFLAGS="$CPPFLAGS"
export CPPFLAGS="$CPPFLAGS $INCLUDES -DHAVE_HELLO"
AC_MSG_CHECKING(PHP version)
AC_TRY_COMPILE([#include <php_version.h>], [
#if PHP_VERSION_ID < 40000
#error this extension requires at least PHP version 4.0.0
#endif
],
[AC_MSG_RESULT(ok)],
[AC_MSG_ERROR([need at least PHP 4.0.0])])
export CPPFLAGS="$OLD_CPPFLAGS"
PHP_SUBST(HELLO_SHARED_LIBADD)
AC_DEFINE(HAVE_HELLO, 1, [ ])
PHP_NEW_EXTENSION(hello, hello.cpp , $ext_shared)
fi
So, if you're struggling with the same problem, use CodeGen_PECL, or adapt the m4 sample above (as well as making sure you've used extern "C" in your header and around the ZEND_GET_MODULE macro)
Again, this is not possible prior to PHP 5.3.0.
Late Static Binding was introduced in PHP 5.3.0 and allows you to do exactly what you want via the static
keyword.
class Super {
protected static $title = 'super';
public static function get_class_name()
{
echo __CLASS__;
}
public static function get_title()
{
echo static::$title;
}
}
class Sub extends Super {
protected static $title = 'sub';
}
get_class_name()
will still return Super
though has __CLASS__
always returns the current class the method being run is declared in (kind of like __FILE__
which always returns the current file no matter if you included it or not).
For that you don't have any choice but to re-declare the function in the Sub
class.
class Super {
protected static $title = 'super';
public static function get_class_name()
{
echo __CLASS__;
}
public static function get_title()
{
echo static::$title;
}
}
class Sub extends Super {
protected static $title = 'sub';
public static function get_class_name()
{
echo __CLASS__;
}
}
It sounds like you probably want to use the server programming interface (SPI) to implement a stored procedure as a C language function running inside the PostgreSQL back-end.
Use SPI_connect
to set up the SPI.
Now SPI_prepare_cursor
a query, then SPI_cursor_open
it. SPI_cursor_fetch
rows from it and SPI_cursor_close
it when done. Note that SPI_cursor_fetch
allows you to fetch batches of rows.
SPI_finish
to clean up when done.
You can return the result rows into a tuplestore as you generate them, avoiding the need to build the whole table in memory. See examples in any of the set-returning functions in the PostgreSQL source code. You might also want to look at the SPI_returntuple
helper function.
See also: C language functions and extending SQL.
If maximum speed is of interest, your client may want to use the libpq binary protocol via libpqtypes so it receives the data produced by your server-side SPI-using procedure with minimal overhead.
You can certainly do this, though I'm not sure anyone has tried. Haskell interoperates with C via its FFI mechanism, and you can certainly:
- Call Haskell from C
so if you can call C from PHP, and that C calls Haskell, you're in business.
Why would you want to do this? Faster, safer, simple code for your core algorithms or safety-critical code, perhaps. Or to take advantage of say, a parallel or multicore server backend via Haskell.
I've written a PHP plugin in C++ with the help of SWIG. It's doable, but it may take a while to get used to the SWIG-compilation cycle. You can start with the SWIG docs for PHP.
Update
As @therefromhere has mentioned, I greatly recommend that you get the book Extending and Embedding PHP. There is almost no documentation to be found online (at least there wasn't in late 2008, early 2009 when I did my PHP plugin). I had to rely on the book for everything. Although sometimes Google Code Search is helpful for finding sample code.