I've written up a small howto on the subject and I can send it along if you
like. The process described in the document works fine for PHP 4.0.6,
although it's a little bit different for the 4.1.0RCs and the final. (There
seemed to have been problems with the build process in 4.0.6 that made
using C++ tricky.)
Basically, when I'm using C++ with PHP, I write the C++ classes and such
and make an interface to PHP in C. Works pretty well for what I've done so
far.
Here's the basic idea (at least for 4.0.6):
0. Use ext_skel to set things up. We'll call the new module "yourmodule".
1. Open up the config.m4 file created and fix things up like the following:
PHP_ARG_ENABLE(yourmodule, whether to enable yourmodule support,
[ --enable-yourmodule Enable yourmodule support]
)
if test "$PHP_YOURMODULE" == "yes"; then
PHP_EXTENSION(yourmodule, $ext_shared)
PHP_REQUIRE_CXX()
fi
2. Open up the Makefile.in file and set it up something like this:
LTLIBRARY_NAME = libyourmodule.la
LTLIBRARY_SOURCES = yourmodule.c
LTLIBRARY_SOURCES_CPP = yourmodulecpp.cpp
LTLIBRARY_SHARED_NAME = yourmodule.la
LTLIBRARY_SHARED_LIBADD = $(YOURMODULE_SHARED_LIBADD)
LTLIBRARY_OBJECTS_X = yourmodulecpp.lo
include $(top_srcdir)/build/dynlib.mk
yourmodule.c will have the stuff that talks to PHP, like the PHP_FUNCTION()
calls an such.
yourmodulecpp.cpp will have all of the C++ stuff. It doesn't talk to PHP
directly, it goes through yourmodule.c. (From what I can tell, you can't
name them both yourmodule.c/cpp. Thinks break.)
3. Set up your C++ header file something like this:
#ifndef __YOURMODULECPP_H__
#define __YOURMODULECPP_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <string>
#ifdef __cplusplus
}
#endif
class MyClass
{
private:
string itsString;
public:
MyClass(string);
~MyClass();
const string getString();
void setString(const string);
};
extern "C" const char* useClass(const char* incoming);
#endif
So basically, wrap C++ stuff in extern "C". useClass() is just a simple
function you can access from C. This example is of course extremely
simplistic, but just as an example, it'll do. Plus, it'll show off the
standard C++ string library, and if it works for you, then it'll prove that
you've got C++ working with PHP.
4. Next, yourmodulecpp.cpp:
#include "yourmodulecpp.h"
MyClass::MyClass(string incoming)
{
itsString = incoming;
}
MyClass::~MyClass()
{
/* not much here, just a default destructor */
}
const string MyClass::getString()
{
return itsString;
}
void MyClass::setString(const string incoming)
{
itsString = incoming;
}
extern "C" const char* useClass(const char* incoming)
{
MyClass blah(incoming);
return blah.getString().c_str();
}
Again, very simple: useClass just takes in a C-like string, instantiates a
MyClass object, calls the MyString::getString() function from the object
and returns a C-like string.
5. php_yourmodule.h shouldn't have to be changed too much, if at all.
yourmodule.c should include a PHP_FUNCTION() call something like this:
PHP_FUNCTION(yourmodule)
{
pval **arg;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) ==
FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(arg);
RETURN_STRING(useClass((*arg)->value.str.val), 1);
}
So basically, take a string from PHP, convert it to a C-like string, pass
it to the useClass() function where it will go through the MyClass object
back in yourmodulecpp.cpp and go through the standard C++ string class, get
returned to C as a C string, then get returned to PHP. Nothing much really
happens, but if it all works, it'll prove C++ is working with C and PHP.
6. Run buildconf in the root PHP directory. When running configure, add a
--enable-yourmodule argument. Run make clean and make.
Now, in PHP 4.0.6, I had problems with the actual build process.
Eventually, make could die and start spitting errors about not being able
to find references to the functions in the standard C++ string library.
This was to be expected, as the linking was being done by the linker using
C semantics, not C++.
To fix this, run the make until it dies. When it does, open up
config_vars.mk in the PHP root directory and change the line that reads
CC=gcc
to
CC=g++
and run make again. Everything should link now and you should be left with
a useable php binary. PHP 4.1.0 doesn't seem to have this problem.
By running a script like:
<?php print yourmodule("hello world"); ?>
you should come up with the output
hello world
Of course, if this works, then the C++ extension worked and all is well.
Getting things to work with apache takes a bit more work, but it's similar
to the config_vars.mk trick. When the Apache build process dies with errors
similar to the CGI build, open up $APACHE_HOME/src/Makefile and make the
same changes (CC=gcc to CC=g++) and run make again. Everything should link
fine and you'll end up with a useable httpd binary.
This is a fairly simple example, but it's worked for me. I was able to get
a few C++ classes I had working fine with PHP. (One of them I've offered up
as a PHP extension, but after a bit of interest, I decided I had better
port it to C just to make it a bit more accessible.)
Anyways, if this doesn't help, I can ship along my howto, it goes into a
bit more detail. And if that doesn't work, let me know.
J
Lars Knudsen wrote:
> Hello everyone.
>
> Can anybody tell me why I get an "Call to undefined function" when
> compiling a module using a C++ compiler (made a small test - it works fine
> when renaming the extension to *.c ... ).
> There are no make errors. The *only* error is that PHP seams unable to
> find the function when compiled using C++.
> Isn't it possible to do C++ in PHP extensions?!?!?
> BTW: I'm using gcc on a Linux RH7.2
> -thanx
>
> mail: [EMAIL PROTECTED]
--
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]