Git Product home page Git Product logo

php-cpp's People

Contributors

adanlobato avatar andot avatar brammel123 avatar dreamsxin avatar ebikt avatar edenreich avatar emielbruijntjes avatar gnat42 avatar guweigang avatar hectorj avatar huxiaoxu2019 avatar jaspervaneck avatar jgmdev avatar mvdwerve avatar ovr avatar rafalgoslawski avatar raidiant avatar rdkamali avatar richard-hordijk avatar ricoantoniofelix avatar robocoder avatar rwols avatar rwoverdijk avatar schoentoon avatar semeleer avatar sjinks avatar swapniel99 avatar thierrylamarre avatar valmat avatar wapmorgan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-cpp's Issues

Segmentation faults when loading multiple extensions on extension shutdown

When you have two extensions written using PHP-CPP and you both add them to your PHP configuration (php.ini):

Any PHP code that uses functionality from one of the loaded extensions will crash when execution ends. The crash happends in extension.cpp in the request_shutdown method, on the following line:;

bool success = extension->endRequest(*environment) && environment->finalize();

This crash is occurs because extension is a NULL pointer. Somehow, something goes wrong when loading two extensions. When I only use one, everything seems to be alright.

I'm still researching the issue.

Make 'this' pointer accessible in Php::Base

When you create your own custom class, you extend from Php::Base. However, inside the methods you do not yet have access to the PHP object as it is seen from user space, so there is no way to update the properties of the object in this method.

Under the hood, the Zend engine passes a this_ptr to every method call, and this pointer is also passed to the Php::Parameters object that is passed to every method call. So we could add a Parameter::self() method to retrieve the Php::Value object that represents the object being called.

However, this Php::Parameters method is not always available (methods are not required to accept parameters), and it would be more logical from an API point of view if the 'this' pointer was not passed in as a parameter, but would always be accessible from custom classes.

Problem: if you added a _self member variable to the Php::Base class, every object would hold a reference to itself, and the refcount would never reach zero, and objects would therefore never get destructed. A smarter solution is thus necessary. My suggestion:

class MyClass : public Php::Base
{
public:
    void myMethod()
    {
        // get access to ourselves
        Php::Object self(this);

        // update a public property
        self["prop1"] = 1234;
    }
};

This is a public issue. I will eventually solve this myself, but since my time is limited and this is an open source project, it would be cool if someone could help me with this.

build error

PHP 5.4.4-14+deb7u5
gcc version 4.7.2 (Debian 4.7.2-5)

Error:
g++ -Wall -c php-config --includes -g -std=c++11 -fpic -o src/argument.o src/argument.cpp
In file included from src/includes.h:94:0,
from src/argument.cpp:9:
src/traverseiterator.h: In member function ‘bool Php::TraverseIterator::read()’:
src/traverseiterator.h:186:64: error: cannot convert ‘zval_struct’ to ‘char__’ in argument passing
make: *_* [src/argument.o] Error 1

Static functions are supported?

I saw that you have implemented the support of static functions. But the corresponding modifier is missing.


Also, I noticed that the super global variables are not working like it should:
php: $_GET['var'] == 5
c++: std::string var = "var";

auto get = Php::GET[var].numericValue();

get == 0

Php::Value G = Php::GLOBALS["_GET"][var];
auto get = G.numericValue();

get == 5
See. full example


From the example in README.md:

Php::Value get_complex_array()
{
    Php::Value r;
    r["a"] = 123;
    r["b"] = 456;
    r["c"][0] = "nested value";
    r["c"][1] = "example";
    return r;
}

This example does not compile:

In file included from /usr/include/phpcpp.h:41:0,
                 from main.cpp:8:
/usr/include/phpcpp/hashmember.h: In instantiation of ‘Php::HashMember<Type> Php::HashMember<Type>::operator[](int) [with Type = std::basic_string<char>]’:
include/variables.h:53:14:   required from here
/usr/include/phpcpp/hashmember.h:154:50: error: no matching function for call to ‘Php::HashMember<int>::add(Php::HashMember<std::basic_string<char> >* const)’
         return _base->get(_index)[index].add(this);
                                                  ^
/usr/include/phpcpp/hashmember.h:154:50: note: candidate is:
In file included from /usr/include/phpcpp.h:41:0,
                 from main.cpp:8:
/usr/include/phpcpp/hashmember.h:387:17: note: Php::HashMember<Type>& Php::HashMember<Type>::add(Php::HashMember<Type>*) [with Type = int]
     HashMember &add(HashMember *parent)
                 ^
/usr/include/phpcpp/hashmember.h:387:17: note:   no known conversion for argument 1 from ‘Php::HashMember<std::basic_string<char> >* const’ to ‘Php::HashMember<int>*’

c++

void value_types(Php::Parameters &params) {
        Php::Value arr = params[0];
        std::cout << "\nNull: "           << bool2str( arr.get("Null").type() == Php::Type::Null );
        std::cout << "\nNumeric: "        << bool2str( arr.get("Numeric").type() == Php::Type::Numeric );
        std::cout << "\nFloat: "          << bool2str( arr.get("Float").type() == Php::Type::Float );
        std::cout << "\nBool: "           << bool2str( arr.get("Bool").type() == Php::Type::Bool );
        std::cout << "\nArray: "          << bool2str( arr.get("Array").type() == Php::Type::Array );
        std::cout << "\nObject: "         << bool2str( arr.get("Object").type() == Php::Type::Object );
        std::cout << "\nString: "         << bool2str( arr.get("String").type() == Php::Type::String );
        std::cout << "\nResource: "       << bool2str( arr.get("Resource").type() == Php::Type::Resource );
        std::cout << "\nConstant: "       << bool2str( arr.get("Constant").type() == Php::Type::Constant );
        std::cout << "\nConstantArray: "  << bool2str( arr.get("ConstantArray").type() == Php::Type::ConstantArray );
        std::cout << "\nCallable: "       << bool2str( arr.get("Callable").type() == Php::Type::Callable );
}
...
extension.add("TestVariables\\value_types",       TestVariables::value_types);

php

$arr = array(
    'Null'            =>   NULL,
    'Numeric'         =>   2014,
    'Float'           =>   3.14,
    'Bool'            =>   true,
    'Array'           =>   array(5,'a' => 33, 'str'),
    'Object'          =>   new stdClass(),
    'String'          =>   'String',
    'Resource'        =>   7,
    'Constant'        =>   5,
    'ConstantArray'   =>   11,
    'Callable'        =>  function () {return 5;}
);
TestVariables\value_types($arr);
---- EXPECTED OUTPUT
Null: Yes
Numeric: Yes
Float: Yes
Bool: Yes
Array: Yes
Object: Yes
String: Yes
Resource: No
Constant: No
ConstantArray: No
Callable: Yes
---- ACTUAL OUTPUT
Null: Yes
Numeric: Yes
Float: Yes
Bool: Yes
Array: Yes
Object: Yes
String: Yes
Resource: No
Constant: No
ConstantArray: No
Callable: No

Did not work: Php::Type::Callable

PS
I will explain where it all came from. I, as I promised, started to write tests. And surfaced minor bugs. I am sure that every bug is fixed one-two lines, but I'm not going to look for how to fix it, and will focus on the tests.

Issue when loading new extension

My new extension doesn't get loaded, instead an error is thrown:

sudo ~/.phpbrew/php/php-5.5.1/sbin/php-fpm                                                                 drgomesp@MacBook-Pro-de-Daniel
[15-Mar-2014 19:38:39] NOTICE: PHP message: PHP Warning:  PHP Startup: hello_world: Unable to initialize module
Module compiled with module API=20090626
PHP    compiled with module API=20121212
These options need to match
 in Unknown on line 0
<br />
<b>Warning</b>:  PHP Startup: hello_world: Unable to initialize module
Module compiled with module API=20090626
PHP    compiled with module API=20121212
These options need to match
 in <b>Unknown</b> on line <b>0</b><br />

Any tips?

Segmentation fault when implementing interface

I have a segmentation fault during module initialization when a class implements a specific interface. This fault is possible when interface is not initialized yet, so interface->_entry is null in classimpl.cpp:1409

    // register the classes
    for (auto &interface : _interfaces)
    {
        // register this interface
        zend_class_implements(_entry TSRMLS_CC, 1, interface->_entry);
    }

Valgrind profile shows this too:

==7155== Memcheck, a memory error detector
==7155== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==7155== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==7155== Command: php
==7155== 
==7155== Invalid read of size 8
==7155==    at 0x6A8967: zend_hash_merge_ex (in /usr/bin/php5)
==7155==    by 0x682067: zend_do_implement_interface (in /usr/bin/php5)
==7155==    by 0x6A1910: zend_class_implements (in /usr/bin/php5)
==7155==    by 0x80D26DF: Php::ClassImpl::initialize(Php::ClassBase*, std::string const&) (classimpl.cpp:1409)
==7155==    by 0x80D8A77: Php::Namespace::initialize(std::string const&) (namespace.cpp:126)
==7155==    by 0x80D8AF3: Php::Namespace::initialize(std::string const&) (namespace.cpp:129)
==7155==    by 0x80D376F: Php::Extension::onStartup(int, int) (extension.cpp:118)
==7155==    by 0x69C3FD: zend_startup_module_ex (in /usr/bin/php5)
==7155==    by 0x6A8553: zend_hash_apply (in /usr/bin/php5)
==7155==    by 0x6A0159: zend_startup_modules (in /usr/bin/php5)
==7155==    by 0x647E24: php_module_startup (in /usr/bin/php5)
==7155==    by 0x72D66C: ??? (in /usr/bin/php5)
==7155==  Address 0x178 is not stack'd, malloc'd or (recently) free'd
==7155== 
==7155== 
==7155== Process terminating with default action of signal 11 (SIGSEGV)
==7155==  Access not within mapped region at address 0x178
==7155==    at 0x6A8967: zend_hash_merge_ex (in /usr/bin/php5)
==7155==    by 0x682067: zend_do_implement_interface (in /usr/bin/php5)
==7155==    by 0x6A1910: zend_class_implements (in /usr/bin/php5)
==7155==    by 0x80D26DF: Php::ClassImpl::initialize(Php::ClassBase*, std::string const&) (classimpl.cpp:1409)
==7155==    by 0x80D8A77: Php::Namespace::initialize(std::string const&) (namespace.cpp:126)
==7155==    by 0x80D8AF3: Php::Namespace::initialize(std::string const&) (namespace.cpp:129)
==7155==    by 0x80D376F: Php::Extension::onStartup(int, int) (extension.cpp:118)
==7155==    by 0x69C3FD: zend_startup_module_ex (in /usr/bin/php5)
==7155==    by 0x6A8553: zend_hash_apply (in /usr/bin/php5)
==7155==    by 0x6A0159: zend_startup_modules (in /usr/bin/php5)
==7155==    by 0x647E24: php_module_startup (in /usr/bin/php5)
==7155==    by 0x72D66C: ??? (in /usr/bin/php5)
==7155==  If you believe this happened as a result of a stack
==7155==  overflow in your program's main thread (unlikely but
==7155==  possible), you can try to increase the size of the
==7155==  main thread stack using the --main-stacksize= flag.
==7155==  The main thread stack size used in this run was 8388608.
==7155== 
==7155== HEAP SUMMARY:
==7155==     in use at exit: 2,336,316 bytes in 17,073 blocks
==7155==   total heap usage: 18,465 allocs, 1,392 frees, 2,492,133 bytes allocated
==7155== 
==7155== LEAK SUMMARY:
==7155==    definitely lost: 0 bytes in 0 blocks
==7155==    indirectly lost: 0 bytes in 0 blocks
==7155==      possibly lost: 642 bytes in 16 blocks
==7155==    still reachable: 2,335,674 bytes in 17,057 blocks
==7155==         suppressed: 0 bytes in 0 blocks
==7155== Rerun with --leak-check=full to see details of leaked memory
==7155== 
==7155== For counts of detected and suppressed errors, rerun with: -v
==7155== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)

Later i found a bug in order of std::move for namespaces, so pointer for an interface wasn't valid. However it will be better to throw an exception to show this information for developers. One more proposed change is to call zend_do_implement_interface function directly instead of zend_class_implements.

Properties

For properties we need documentation, and a better system for defining properties in which the setter and getter method can be explicitly set (instead of setting properties directly via the Zend engine, without any checking)

Windows build

Hi,

As part of making php-cpp builds using config file, I began to port it to windows (using vc13 and later vc11 to match upstream windows binary).

1st result:

https://gist.github.com/pierrejoye/593d8bf8ba3c5a81987c

Looks like some cpp features used need some tweeks.

besides:

1st config.w32 (pretty much the same then for config.m4):

// vim:ft=javascript
// $Id$

ARG_ENABLE('php-cpp', 'Enable php-cpp library', 'no');

if (PHP_PHP_CPP != "no") {
ADD_SOURCES("sapi/php-cpp/src", "argument.cpp base.cpp callable.cpp classbase.cpp exception.cpp global.cpp globals.cpp
hashmember.cpp iterator.cpp members.cpp modifiers.cpp namespace.cpp object.cpp origexception.cpp
parameters.cpp streambuf.cpp streams.cpp super.cpp value.cpp valueiterator.cpp", "phpcpp");
SAPI('phpcpp', 'src/extension.cpp', 'php' + PHP_VERSION + 'phpcpp.lib');
// PHP_INSTALL_HEADERS("sapi/phpcpp", "src/*.h");
}

it will allow to build php-cpp as part of php as a "sapi", which makes allows some optimizations later. Once it works I will try to provide another one to rely only on phpize, so php-cpp can be distributed easily.

php version supported

What minimal PHP version supported by PH-CPP. I cannot compile it for PHP ver.5.3.10....?

Non-copied strings

Strings are always fully copied into a Value object. This is a waste of time, because some strings are hardcoded, and no copy to dynamic memory is necessary.

This code make for example an unnecessary copy of a string:

Value x("example");

Need help with converting a recursive function

make is throwing me lots of errors Here are some of them:
error: is_array is not a member of Php
error: array_key_exists is not a member of Php
error: isset is not a member of Php
error: ambiguous overload for ‘operator[]’ (operand types are ‘Php::Array’ and ‘Php::Value’)
error: ambiguous overload for 'operator[]' (operand types are 'Php::Value' and 'Php::Value')

PHP code: http://pastebin.com/ZMdkarPu
C++ code: http://pastebin.com/8U11V90V

Trying to compile simple extension

I'm trying to compile the following extension:

#include <phpcpp.h>
#include <iostream>

void myFunction()
{
    std::cout << "example output" << std::endl;
}

extern "C" {
    PHPCPP_EXPORT void *get_module() {
        static Php::Extension extension("hello_world", "1.0");
        extension.add("myFunction", myFunction);
        return extension;
    }
}

With the following Makefile:

#
#   Makefile template
#
#   This is an example Makefile that can be used by anyone who is building
#   his or her own PHP extensions using the PHP-CPP library. 
#
#   In the top part of this file we have included variables that can be
#   altered to fit your configuration, near the bottom the instructions and
#   dependencies for the compiler are defined. The deeper you get into this
#   file, the less likely it is that you will have to change anything in it.
#

#
#   Name of your extension
#
#   This is the name of your extension. Based on this extension name, the
#   name of the library file (name.so) and the name of the config file (name.ini)
#   are automatically generated
#

NAME                =   hello_world


#
#   Php.ini directories
#
#   In the past, PHP used a single php.ini configuration file. Today, most
#   PHP installations use a conf.d directory that holds a set of config files,
#   one for each extension. Use this variable to specify this directory.
#

INI_DIR             =   /Users/drgomesp/.phpbrew/php/php-5.3.28/etc


#
#   The extension dirs
#
#   This is normally a directory like /usr/lib/php5/20121221 (based on the 
#   PHP version that you use. We make use of the command line 'php-config' 
#   instruction to find out what the extension directory is, you can override
#   this with a different fixed directory
#

EXTENSION_DIR       =   $(shell php-config --extension-dir)


#
#   The name of the extension and the name of the .ini file
#
#   These two variables are based on the name of the extension. We simply add
#   a certain extension to them (.so or .ini)
#

EXTENSION           =   ${NAME}.so
INI                 =   ${NAME}.ini


#
#   Compiler
#
#   By default, the GNU C++ compiler is used. If you want to use a different
#   compiler, you can change that here. You can change this for both the 
#   compiler (the program that turns the c++ files into object files) and for
#   the linker (the program that links all object files into the single .so
#   library file. By default, g++ (the GNU C++ compiler) is used for both.
#

COMPILER            =   clang
LINKER              =   clang


#
#   Compiler and linker flags
#
#   This variable holds the flags that are passed to the compiler. By default, 
#   we include the -O2 flag. This flag tells the compiler to optimize the code, 
#   but it makes debugging more difficult. So if you're debugging your application, 
#   you probably want to remove this -O2 flag. At the same time, you can then 
#   add the -g flag to instruct the compiler to include debug information in
#   the library (but this will make the final libphpcpp.so file much bigger, so
#   you want to leave that flag out on production servers).
#
#   If your extension depends on other libraries (and it does at least depend on
#   one: the PHP-CPP library), you should update the LINKER_DEPENDENCIES variable
#   with a list of all flags that should be passed to the linker.
#

COMPILER_FLAGS      =   -arch x86_64 -arch i386 -c -I. `php-config --includes` -g -std=c++11 -fpic -o
LINKER_FLAGS        =   -shared -undefined dynamic_lookup `php-config --ldflags`
LINKER_DEPENDENCIES =   -lphpcpp


#
#   Command to remove files, copy files and create directories.
#
#   I've never encountered a *nix environment in which these commands do not work. 
#   So you can probably leave this as it is
#

RM                  =   rm -f
CP                  =   cp -f
MKDIR               =   mkdir -p


#
#   All source files are simply all *.cpp files found in the current directory
#
#   A built-in Makefile macro is used to scan the current directory and find 
#   all source files. The object files are all compiled versions of the source
#   file, with the .cpp extension being replaced by .o.
#

SOURCES             =   $(wildcard *.cpp)
OBJECTS             =   $(SOURCES:%.cpp=%.o)


#
#   From here the build instructions start
#

all:            ${OBJECTS} ${EXTENSION}

${EXTENSION}:   ${OBJECTS}
        ${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} ${LINKER_DEPENDENCIES}

${OBJECTS}:
        ${COMPILER} ${COMPILER_FLAGS} $@ ${@:%.o=%.cpp}

install:        
        ${CP} ${EXTENSION} ${EXTENSION_DIR}
        ${CP} ${INI} ${INI_DIR}

clean:
        ${RM} ${EXTENSION} ${OBJECTS}

And the following error occurs:

make                                                                                                       drgomesp@MacBook-Pro-de-Daniel
clang -arch x86_64 -arch i386 -c -I. `php-config --includes` -g -std=c++11 -fpic -o Main.o Main.cpp
In file included from Main.cpp:2:
In file included from /usr/local/include/phpcpp.h:46:
/usr/local/include/phpcpp/iterator.h:131:72: error: unknown type name 'uint'; did you mean 'int'?
    static int key(struct _zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key);
                                                                       ^
/usr/local/include/phpcpp/iterator.h:131:91: error: unknown type name 'ulong'; did you mean 'long'?
    static int key(struct _zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key);
                                                                                          ^
2 errors generated.
make: *** [Main.o] Error 1

I'm on OSX, with PHP-CPP compiled and installed to /usr/local/include.

Any tips?

PHP::Value::Array appending is causing `zend_mm_heap corrupted`

I was debating using this library to build some extensions, but I'm hitting an error I don't quite understand. The error is as posted above, zend_mm_heap corrupted.

System Information

$ php --version
PHP 5.5.9 (cli) (built: Apr  6 2014 20:53:20)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.2, Copyright (c) 1999-2013, by Zend Technologies
    with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans

Extension Code

#include <phpcpp.h>

Php::Value array_append(Php::Parameters &parameters)
{

    parameters[0].set(parameters[0].count(), parameters[1]);

    return parameters[0];
}

extern "C" {
    PHPCPP_EXPORT void *get_module() {
        static Php::Extension extension("my_example", "1.0");

        extension.add("array_append", array_append, {
            Php::ByVal("a", Php::Type::Array),
            Php::ByVal("b", Php::Type::String)
        });

        return extension;
    }
}

Failing PHP Code

<?php

$input = [];

for ($i = 0; $i < 50000; $i++) {
    echo $i . PHP_EOL;
    $input = array_append($input, 'test');
}

Output

1
2
3
....
2990
2991
zend_mm_heap corrupted

Notes:

When passed by reference(Php::ByRef) the error does not occur, though this changes how the function works.

The following implementation appears to not having this corruption issue:

Php::Value array_append(Php::Parameters &parameters)
{

    Php::Array array = parameters[0];

    array.set(parameters[0].count(), parameters[1]);

    return array;
}

module API value not matching

I made a small example extension to check whether I am able to load my example extension, but this fails because the module APIs of the extension and my PHP installation does not match.

jan@urdbrunnen ~/Workspace/PHP-CPP$ make
g++ -Wall -c -O2 -std=c++11 -fpic -o example.o example.cpp
g++ -shared -o example.so example.o -lphpcpp
jan@urdbrunnen ~/Workspace/PHP-CPP$ sudo make install
cp -f example.so /usr/lib/php/extensions/no-debug-non-zts-20100525
cp -f example.ini /Library/Server/Web/Config/php
jan@urdbrunnen ~/Workspace/PHP-CPP$ php -m
PHP Warning:  PHP Startup: example: Unable to initialize module
Module compiled with module API=268435456
PHP    compiled with module API=20100525
These options need to match
 in Unknown on line 0

It also feels like I always get another module API version (incl. negative!)

Module compiled with module API=-1342177280

Is Php-cpp runing windows

Hi,
I want write php extension for windows(dll) . But i didn't see anywhere that related documents for php-cpp.
Is this possible?

Creating class instances

The PHP-CPP library does not yet have a way to instantiate classes. You can store already-created objects in a Php::Value object, but there is no way to create a new instance.

My suggestion is to have a Php::Object class (that derives from Php::ForcedValue) and that can be used to create new instances. The constructor gets the name of the classes, and a list of parameters that are passed to the __construct function:

// create a new PHP DateTime object representing the current time
Php::Object now("DateTime", "now");

// show it
std::cout << now.call("format", "Y-m-d H:i:s") << std::endl;

This is a public issue. I will eventually solve this myself, but since my time is limited and this is an open source project, it would be cool if someone could help me with this.

Inconsistent MixedObejct declaration

include/base.h:16 class MixedObject;
src/mixedobject.h:19 struct MixedObject;

I suppose struct is meant, as there is no implementation and members are public anyway.

More super globals

We already have a Php::GLOBALS variable to access all global variables. In line with PHP code, we also need a Php::GET, Php::REQUEST, Php::POST, Php::COOKIES and Php::SERVER variable.

Cloning objects

In the classbase.cpp file in the source directory, there is a clone_object() function that is not yet implemented. As a consequence, we do not yet have a good way to clone objects. This should be implemented. Cloning an object should (first) run the normal clone operation on the underlying Php::Value/zval object (which should create a new Php::Value/zval object with the same properties as the original one), and then it should call the copy constructor of the original custom C++ class to create a new instance of the copied class.

This is a public issue. I will eventually solve this myself, but since my time is limited and this is an open source project, it would be cool if someone could help me with this.

5.6 and master does not have pass_rest_by_reference anymore

pass_rest_by_reference is not used anymore in 5.6+

FYI, from the upgrading guide:

  • The pass_rest_by_reference argument of the ZEND_BEGIN_ARG_INFO and
  • ZEND_BEGIN_ARG_INFO_EX() is no longer used. The value passed to it is ignored.
  • Instead a variadic argument is created using ZEND_ARG_VARIADIC_INFO():
  •  ZEND_ARG_VARIADIC_INFO(0, name) /\* pass rest by value */
    
  •  ZEND_ARG_VARIADIC_INFO(1, name) /\* pass rest by reference */
    
  •  ZEND_ARG_VARIADIC_INFO(ZEND_SEND_PREFER_REF, name)
    
  •      /\* pass rest by prefer-ref */
    
  • ZEND_ARG_VARIADIC_INFO() should only be used for the last argument.
  • The following changes were applied to the zend_arg_info struct:
  •   typedef struct _zend_arg_info {
    
  •       const char *class_name;
    
  •       zend_uint class_name_len;
    
  •       zend_uchar type_hint;
    
  •  +    zend_uchar pass_by_reference;
    
  •       zend_bool allow_null;
    
  •  -    zend_bool pass_by_reference;
    
  •  +    zend_bool is_variadic;
    
  •   } zend_arg_info;
    
  • The following changes were applied to the zend_internal_function_info struct:
  •   typedef struct _zend_internal_function_info {
    
  •       zend_uint required_num_args;
    
  •       zend_uchar _type_hint;
    
  •       zend_bool return_reference;
    
  •  -    zend_bool pass_rest_by_reference;
    
  •  +    zend_bool _allow_null;
    
  •  +    zend_bool _is_variadic;
    
  •   } zend_internal_function_info;
    
  • The CHECK_ARG_SEND_TYPE(), ARG_MUST_BE_SENT_BY_REF(),
  • ARG_SHOULD_BE_SENT_BY_REF() and ARG_MAY_BE_SENT_BY_REF() macros now assume
  • that the argument passed to them is a zend_function* and that it is non-NULL.

Declaring PHP Interfaces

We should be able to declare Interfaces in C++ that are then available in PHP. And we should be able to create in C++ classes that implement these interfaces.

It this feature already exists, the documentation should then be updated with examples.

De-virtualization of magic methods

Magic methods can be resolved at compile time. This means that a user has more freedom in choosing the signature for their magic methods.

Also: now I think that __compare is a better alternative for the operator<, because now we call the operator< twice, instead of only once.

Global Php::SERVER is not working

First i want to thank you about this wonderful piece of software which makes my life so much easier 👍

My Setting:
Windows 7(x64), Apache 2.4.7(x86), Php 5.5.10ts(x86) and Visual Studio 2013.

I'm able to compile php-cpp with php and everything works except the global Php::SERVER. I was able to debug my Problem and noticed that "PG(http_globals)[_index]" _index == 3 -> get me an NULL Pointer. Can you reproduce that or could that be a problem with my setting ?

BIG THX

Segmentation fault: 11

example.cpp

#include <phpcpp.h>

using namespace std;

class Dummy : public Php::Base {
  public:
    Php::Value add(Php::Parameters &params) {
      return 0;
    }
};

extern "C" {
  PHPCPP_EXPORT void *get_module() {
    static Php::Extension extension("example", "0.1");
    Php::Class<Dummy> dummy("Example\\Dummy");

    dummy.method("add", &Dummy::add, {
      Php::ByVal("a", Php::Type::Numeric),
      Php::ByVal("b", Php::Type::Numeric)
    });

    extension.add(std::move(dummy));
    return extension;
  }
}

example.ini

extension=example.so

Makefile changes

  • NAME = example
  • INI_DIR = /Library/Server/Web/Config/php

Building

jan@urdbrunnen ~/Workspace/Example$ make
g++ -Wall -c -O2 -std=c++11 -fpic -o example.o example.cpp
g++ -shared -o example.so example.o -lphpcpp

jan@urdbrunnen ~/Workspace/Example$ sudo make install
cp -f example.so /usr/lib/php/extensions/no-debug-non-zts-20100525
cp -f example.ini /Library/Server/Web/Config/php

jan@urdbrunnen ~/Workspace/Example$ php -m | grep example
example

example.php

$dummy = new Example\Dummy;
$dummy->add(1, 2);

Output

jan@urdbrunnen ~/Workspace/Example$ php example.php
int(0)
Segmentation fault: 11

Php::echo()

I have already mentioned this feature.
The fact that php uses its own output stream for printing text.
std::cout sends data to standard output stream, std::cerr in the standard error output stream.
std::cout can only be used in CLI mode php. For creating web applications, this method does not work.
The simplest method to solve the issue is to write a wrapper around the zend_write:

void echo(std::string str) {
    zend_write( str.c_str(), str.size());
}

I just checked. This function works!
Basically, in this form it is enough, but we can go ahead and implement something like this:

Php::echo << "PI equals " << 3.14;

make fails on Ubuntu 12.04

I've tried to make PHP-CPP (v0.9) on my laptop, but it fails 😢

jan@himinbjorg ~/Workspace$ git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP.git
Cloning into 'PHP-CPP'...
remote: Reusing existing pack: 2337, done.
remote: Counting objects: 176, done.
remote: Compressing objects: 100% (176/176), done.
remote: Total 2513 (delta 114), reused 0 (delta 0)
Receiving objects: 100% (2513/2513), 889.51 KiB | 379.00 KiB/s, done.
Resolving deltas: 100% (1648/1648), done.
Checking connectivity... done.
jan@himinbjorg ~/Workspace$ cd PHP-CPP
jan@himinbjorg ~/Workspace/PHP-CPP (master)$ git checkout v0.9
jan@himinbjorg ~/Workspace/PHP-CPP ((v0.9))$ make
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/argument.o src/argument.cpp
In file included from src/includes.h:93:0,
                 from src/argument.cpp:9:
src/notimplemented.h:43:13: error: looser throw specifier for ‘virtual Php::NotImplemented::~NotImplemented()’
In file included from /usr/include/c++/4.7/new:42:0,
                 from /usr/include/c++/4.7/ext/new_allocator.h:34,
                 from /usr/include/x86_64-linux-gnu/c++/4.7/./bits/c++allocator.h:34,
                 from /usr/include/c++/4.7/bits/allocator.h:48,
                 from /usr/include/c++/4.7/string:43,
                 from src/includes.h:14,
                 from src/argument.cpp:9:
/usr/include/c++/4.7/exception:66:13: error:   overriding ‘virtual std::exception::~exception() noexcept (true)’
make: *** [src/argument.o] Error 1

GCC Version

jan@himinbjorg ~/Workspace/PHP-CPP ((v0.9))$ gcc --version
gcc (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

G++ Version

jan@himinbjorg ~/Workspace/PHP-CPP ((v0.9))$ g++ --version
g++ (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Ubuntu Version

jan@himinbjorg ~/Workspace/PHP-CPP ((v0.9))$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.4 LTS"

fatal error: php.h: No such file or directory

This seems to be related to missing php-dev. I have php installed from source.

cd src; make
make[1]: Entering directory `/usr/local/src/PHP-CPP/src'
g++ -g -Wno-write-strings  -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -O2 -std=c++11 -fpic -o argument.o argument.cpp
In file included from argument.cpp:9:0:
includes.h:33:17: fatal error: php.h: No such file or directory
compilation terminated.
make[1]: *** [argument.o] Error 1
make[1]: Leaving directory `/usr/local/src/PHP-CPP/src'
make: *** [all] Error 2

Make test only works after make install

The extension which is compiled for make test assumes an installed phpcpp and refers to a phpcpp.h. If the test should happen before the installation (which would be a good thing imho), the test extension should build against the current working directory.

OSX 10.9.3
mario@xenjibook ~/D/S/PHP-CPP> g++ -v master!?
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

Fix samples?

hi,

First thanks a lot for this awesome c++ helper!

It would be nice to add config.m4/w32 to the examples. Doing so will allow anyone to compile extensions using phpize and even better, release them via pecl :)

Keep the good work!

A small suggestion

I have a suggestion.
Now the methods Class::method(...) return type void.
And when declaring class we write something like this:

Php::Class<Counter> counter("Counter");
counter.method("increment", &Counter::increment);
// some comment
counter.method("decrement", &Counter::decrement);
counter.method("value", &Counter::value);

// add the class to the extension
myExtension.add(std::move(counter));

If slightly modify the prototype (slightly fix just 15 consecutive lines):

void method(const char *name, void  (T::*method)(), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast<method_callback_0>(method), flags,  args);}
//...

to

Class&& method(const char *name, void  (T::*method)(), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast<method_callback_0>(method), flags,  args); return *this;}
//...

Then we can write this:

// add the class to the extension
myExtension.add
    (
        Php::Class<Counter>("Counter")
            .method("increment", &Counter::increment)
            // some comment
            .method("decrement", &Counter::decrement)
            .method("value", &Counter::value)
    );

The same applies to the Class::property(...)
In such record, there are no ambiguities and potential pitfalls for the compiler. And return *this by ref does not copy. Therefore, the additional overhead there is no.
Of the advantages I see

  1. Nice view of writing. Like jQuery.
  2. All entities related to a class of visually grouped.
  3. There is no need to use std::move(...) (object of Php::Class in such a record already rvalue)
  4. The previous record form can still be used.

That would have been sure that it is really possible to do without std::move(...) I have prepared some illustrating examples:

#include <iostream>

class Chaining
{
public:

    Chaining() {}

    Chaining& meth1() &
    {
        std::cout << "meth1 &" << std::endl;
    }

    Chaining& meth2() &
    {
        std::cout << "meth2 &" << std::endl;
    }

    Chaining& meth3() &
    {
        std::cout << "meth3 &" << std::endl;
    }

    Chaining&& meth1() &&
    {
        std::cout << "meth1 &&" << std::endl;
    }

    Chaining&& meth2() &&
    {
        std::cout << "meth2 &&" << std::endl;
    }

    Chaining&& meth3() &&
    {
        std::cout << "meth3 &&" << std::endl;
    }
};

int main(){
    Chaining()
        .meth1()
        .meth2()
        .meth3();

    Chaining obj;
    obj.meth1();
    obj.meth2();
    obj.meth3();

    return 0;
};

output:

meth1 &&
meth2 &&
meth3 &&
meth1 &
meth2 &
meth3 &

#include <iostream>

class Chaining
{
public:

    Chaining() {}

    Chaining& meth1()
    {
        std::cout << "meth1 &" << std::endl;
    }

    Chaining& meth2()
    {
        std::cout << "meth2 &" << std::endl;
    }

    Chaining& meth3()
    {
        std::cout << "meth3 &" << std::endl;
    }
};

int main(){
    Chaining()
        .meth1()
        .meth2()
        .meth3();

    Chaining obj;
    obj.meth1();
    obj.meth2();
    obj.meth3();

    return 0;
};

output:

meth1 &
meth2 &
meth3 &
meth1 &
meth2 &
meth3 &

#include <iostream>

class Chaining
{
public:
    Chaining() {}

    Chaining&& meth1()
    {
        std::cout << "meth1 &&" << std::endl;
    }

    Chaining&& meth2()
    {
        std::cout << "meth2 &&" << std::endl;
    }

    Chaining&& meth3()
    {
        std::cout << "meth3 &&" << std::endl;
    }
};

int main(){
    Chaining()
        .meth1()
        .meth2()
        .meth3();

    Chaining obj;
    obj.meth1();
    obj.meth2();
    obj.meth3();

    return 0;
};

output:

meth1 &&
meth2 &&
meth3 &&
meth1 &&
meth2 &&
meth3 &&

Compilation error : ambiguous call

Hi!
I get a compilation error with latest sources, here is the build output :

g++ -Wall -c -g -std=c++11 -fpic -o common/modifiers.o common/modifiers.cpp
g++ -Wall -c -g -std=c++11 -fpic -o common/streambuf.o common/streambuf.cpp
g++ -Wall -c -g -std=c++11 -fpic `php-config --includes` -o zend/base.o zend/base.cpp
g++ -Wall -c -g -std=c++11 -fpic `php-config --includes` -o zend/callable.o zend/callable.cpp
g++ -Wall -c -g -std=c++11 -fpic `php-config --includes` -o zend/classbase.o zend/classbase.cpp
g++ -Wall -c -g -std=c++11 -fpic `php-config --includes` -o zend/classimpl.o zend/classimpl.cpp
g++ -Wall -c -g -std=c++11 -fpic `php-config --includes` -o zend/extension.o zend/extension.cpp
g++ -Wall -c -g -std=c++11 -fpic `php-config --includes` -o zend/extensionimpl.o zend/extensionimpl.cpp
zend/extensionimpl.cpp: In member function ‘zend_module_entry* Php::ExtensionImpl::module()’:
zend/extensionimpl.cpp:267:6: error: call of overloaded ‘apply(Php::ExtensionImpl::module()::<lambda(const string&, Php::Function&)>)’ is ambiguous
zend/extensionimpl.cpp:267:6: note: candidates are:
In file included from zend/includes.h:74:0,
                 from zend/extensionimpl.cpp:7:
zend/../include/namespace.h:185:10: note: void Php::Namespace::apply(const std::function<void(const std::basic_string<char>&, Php::Function&)>&)
zend/../include/namespace.h:195:10: note: void Php::Namespace::apply(const std::function<void(const std::basic_string<char>&, Php::ClassBase&)>&)
zend/extensionimpl.cpp: In member function ‘void Php::ExtensionImpl::initialize()’:
zend/extensionimpl.cpp:293:6: error: call of overloaded ‘apply(Php::ExtensionImpl::initialize()::<lambda(const string&, Php::ClassBase&)>)’ is ambiguous
zend/extensionimpl.cpp:293:6: note: candidates are:
In file included from zend/includes.h:74:0,
                 from zend/extensionimpl.cpp:7:
zend/../include/namespace.h:185:10: note: void Php::Namespace::apply(const std::function<void(const std::basic_string<char>&, Php::Function&)>&)
zend/../include/namespace.h:195:10: note: void Php::Namespace::apply(const std::function<void(const std::basic_string<char>&, Php::ClassBase&)>&)
make: *** [zend/extensionimpl.o] Error 1

BUILD FAILED (exit value 2, total time: 6s)

I use the given MAKEFILE with no modifications.
My g++ version is 4:4.7.3-1ubuntu10

Found a fix here : https://stackoverflow.com/questions/4111647/disambiguating-calls-to-functions-taking-stdfunctions
After applying it (see https://github.com/hectorj/PHP-CPP/compare/fixAmbiguousLambdaCalls1), it compiles but the make test fails (100%).
Here is the test output but it doesn't say much except that everything fails :

PHP         : /usr/bin/php 
PHP_SAPI    : cli
PHP_VERSION : 5.4.9-4ubuntu2.4
ZEND_VERSION: 2.4.0
PHP_OS      : Linux - Linux hjwm 3.8.0-35-generic #50-Ubuntu SMP Tue Dec 3 01:24:59 UTC 2013 x86_64
INI actual  : /etc/php5/cli/php.ini
More .INIs  : /etc/php5/cli/conf.d/10-pdo.ini,/etc/php5/cli/conf.d/20-curl.ini,/etc/php5/cli/conf.d/20-gd.ini,/etc/php5/cli/conf.d/20-gmp.ini,/etc/php5/cli/conf.d/20-mysql.ini,/etc/php5/cli/conf.d/20-mysqli.ini,/etc/php5/cli/conf.d/20-pdo_mysql.ini,/etc/php5/cli/conf.d/20-xdebug.ini,/etc/php5/cli/conf.d/20-xmlrpc.ini,/etc/php5/cli/conf.d/20-xsl.ini,/etc/php5/cli/conf.d/mcrypt.ini,/etc/php5/cli/conf.d/phpbitcoin.ini,/etc/php5/cli/conf.d/ssh2.ini 
CWD         : /var/www/PHP-CPP-src/tests
Extra dirs  : 
VALGRIND    : Not used
=====================================================================
Running selected tests.
FAIL Test constructor & destructor [php/phpt/class_obj/001.phpt] 
FAIL Test constructor & destructor [php/phpt/class_obj/002.phpt] 
FAIL Test comparable objects [php/phpt/class_obj/003-comparable.phpt] 
FAIL Test class with static function [php/phpt/class_obj/004-static-funct.phpt] 
FAIL Test class with static property and class constant [php/phpt/class_obj/005-static-prop.phpt] 
FAIL Iterate array [php/phpt/valueiterator/001.phpt] 
FAIL Iterate object of stdClass [php/phpt/valueiterator/002.phpt] 
FAIL Iterate object [php/phpt/valueiterator/003.phpt] 
FAIL Iterate itarable oblect [php/phpt/valueiterator/004.phpt] 
FAIL Iterate itarable oblect [php/phpt/valueiterator/005.phpt] 
FAIL Iterate itarable oblect [php/phpt/valueiterator/006.phpt] 
FAIL Iterate internal array [php/phpt/valueiterator/007-Iterate-internal-array.phpt] 
FAIL Global variables in PHP-CPP [php/phpt/variables/001-process_globals.phpt] 
FAIL get_complex_array [php/phpt/variables/002-get_complex_array.phpt] 
FAIL get_complex_array [php/phpt/variables/003-value-types.phpt] 
FAIL Test variables defined in PHP-CPP [php/phpt/variables/004-store-scalar-variables.phpt] 
FAIL cast objects to scalars [php/phpt/variables/005-cast-objects-to-scalars.phpt] 
FAIL Test Php::Value casting operators (object to string) [php/phpt/variables/006-casting-obj2str.phpt] 
FAIL Test Php::Value overloaded operators [php/phpt/variables/007-overloaded-operators.phpt] 
FAIL Test Php::Value arrays [php/phpt/variables/008-value-arrays.phpt] 
FAIL Test Php::Value object #1 [php/phpt/variables/009-value-object.phpt] 
FAIL Test Php::Value object #2 [php/phpt/variables/010-value-object2.phpt] 
FAIL Test Php::Value casting operators [php/phpt/variables/011-value-casting-operators.phpt] 
FAIL Test Php::Value casting operators (double) [php/phpt/variables/012-value-casting-operators-double.phpt] 
FAIL calling-php-functions from userspace [php/phpt/variables/013-calling-php-functions.phpt] 
FAIL calling-php-Callback-functions [php/phpt/variables/014-calling-php-functions.phpt] 
FAIL calling-php-Callback-functions (lambda) [php/phpt/variables/015-calling-php-functions.phpt] 
FAIL calling-php-Callback-functions (__invoke) [php/phpt/variables/016-calling-php-functions.phpt] 
FAIL calling-php-Callback-functions (method of class) [php/phpt/variables/017-calling-php-functions.phpt] 
FAIL calling-php-callable [php/phpt/variables/018-calling-php-functions.phpt] 
FAIL get_complex_array (test HashMember #1) [php/phpt/variables/019-HashMember-1.phpt] 
FAIL get_complex_array (test HashMember #2) [php/phpt/variables/020-HashMember-2.phpt] 
FAIL get_complex_array (test HashMember #3) [php/phpt/variables/021-HashMember-3.phpt] 
FAIL get_complex_array (test HashMember #4) [php/phpt/variables/022-HashMember-4.phpt] 
=====================================================================
Number of tests :   34                34
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :   34 (100.0%) (100.0%)
Expected fail   :    0 (  0.0%) (  0.0%)
Tests passed    :    0 (  0.0%) (  0.0%)
---------------------------------------------------------------------
Time taken      :    2 seconds
=====================================================================

=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
Test constructor & destructor [php/phpt/class_obj/001.phpt]
Test constructor & destructor [php/phpt/class_obj/002.phpt]
Test comparable objects [php/phpt/class_obj/003-comparable.phpt]
Test class with static function [php/phpt/class_obj/004-static-funct.phpt]
Test class with static property and class constant [php/phpt/class_obj/005-static-prop.phpt]
Iterate array [php/phpt/valueiterator/001.phpt]
Iterate object of stdClass [php/phpt/valueiterator/002.phpt]
Iterate object [php/phpt/valueiterator/003.phpt]
Iterate itarable oblect [php/phpt/valueiterator/004.phpt]
Iterate itarable oblect [php/phpt/valueiterator/005.phpt]
Iterate itarable oblect [php/phpt/valueiterator/006.phpt]
Iterate internal array [php/phpt/valueiterator/007-Iterate-internal-array.phpt]
Global variables in PHP-CPP [php/phpt/variables/001-process_globals.phpt]
get_complex_array [php/phpt/variables/002-get_complex_array.phpt]
get_complex_array [php/phpt/variables/003-value-types.phpt]
Test variables defined in PHP-CPP [php/phpt/variables/004-store-scalar-variables.phpt]
cast objects to scalars [php/phpt/variables/005-cast-objects-to-scalars.phpt]
Test Php::Value casting operators (object to string) [php/phpt/variables/006-casting-obj2str.phpt]
Test Php::Value overloaded operators [php/phpt/variables/007-overloaded-operators.phpt]
Test Php::Value arrays [php/phpt/variables/008-value-arrays.phpt]
Test Php::Value object #1 [php/phpt/variables/009-value-object.phpt]
Test Php::Value object #2 [php/phpt/variables/010-value-object2.phpt]
Test Php::Value casting operators [php/phpt/variables/011-value-casting-operators.phpt]
Test Php::Value casting operators (double) [php/phpt/variables/012-value-casting-operators-double.phpt]
calling-php-functions from userspace [php/phpt/variables/013-calling-php-functions.phpt]
calling-php-Callback-functions [php/phpt/variables/014-calling-php-functions.phpt]
calling-php-Callback-functions (lambda) [php/phpt/variables/015-calling-php-functions.phpt]
calling-php-Callback-functions (__invoke) [php/phpt/variables/016-calling-php-functions.phpt]
calling-php-Callback-functions (method of class) [php/phpt/variables/017-calling-php-functions.phpt]
calling-php-callable [php/phpt/variables/018-calling-php-functions.phpt]
get_complex_array (test HashMember #1) [php/phpt/variables/019-HashMember-1.phpt]
get_complex_array (test HashMember #2) [php/phpt/variables/020-HashMember-2.phpt]
get_complex_array (test HashMember #3) [php/phpt/variables/021-HashMember-3.phpt]
get_complex_array (test HashMember #4) [php/phpt/variables/022-HashMember-4.phpt]
=====================================================================

Any idea on how to fix this?

How to getting started?

Is it compatible with Windows(XP/7/8)?
What's the development environment? PHP version, vc++ ?
I known how to use a c compiler.

make fails on Mac OSX

After building PHP-CPP on my laptop (Ubuntu) failed, I've tried to build it on my Mac OSX laptop (branch: master), but it fails 😢 Do I need a specific minimum PHP version to build PHP-CPP?

jan@urdbrunnen ~/Workspace$ git clone [email protected]:CopernicaMarketingSoftware/PHP-CPP.git
jan@urdbrunnen ~/Workspace$ cd PHP-CPP
jan@urdbrunnen ~/Workspace$ make
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/argument.o src/argument.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/base.o src/base.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/callable.o src/callable.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/classbase.o src/classbase.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/exception.o src/exception.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/extension.o src/extension.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/global.o src/global.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/globals.o src/globals.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/hashmember.o src/hashmember.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/iterator.o src/iterator.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/members.o src/members.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/modifiers.o src/modifiers.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/namespace.o src/namespace.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/object.o src/object.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/origexception.o src/origexception.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/parameters.o src/parameters.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/super.o src/super.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/value.o src/value.cpp
g++ -Wall -c -I. -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/ext -I/usr/include/php5/Zend -I/usr/include/php5/TSRM -g -std=c++11 -fpic -o src/valueiterator.o src/valueiterator.cpp
src/valueiterator.cpp:96:5: error: use of undeclared identifier 'zend_hash_get_current_key_zval_ex'; did you mean 'zend_hash_get_current_data_ex'?
    zend_hash_get_current_key_zval_ex(_table, key._val, &_position);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    zend_hash_get_current_data_ex
/usr/include/php5/Zend/zend_hash.h:181:14: note: 'zend_hash_get_current_data_ex' declared here
ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
             ^
src/valueiterator.cpp:96:47: error: cannot initialize a parameter of type 'void **' with an lvalue of type 'struct _zval_struct *'
    zend_hash_get_current_key_zval_ex(_table, key._val, &_position);
                                              ^~~~~~~~
/usr/include/php5/Zend/zend_hash.h:181:66: note: passing argument to parameter 'pData' here
ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
                                                                 ^
2 errors generated.
make: *** [src/valueiterator.o] Error 1

GCC Version

jan@urdbrunnen ~/Workspace/PHP-CPP$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

G++ Version

jan@urdbrunnen ~/Workspace/PHP-CPP$ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

Mac OSX Version

jan@urdbrunnen ~/Workspace/PHP-CPP$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.9.2
BuildVersion:   13C64

Add class inheritance support on extension level

Currently, there is no simple way to define inheritance for classes and interfaces from PHP side of view. All classes are registered via zend_register_internal_class, no usage of zend_register_internal_class_ex that allow to define inheritance for classes.

My suggestion is to add a constructor for Php::Class that will accept another instance of Php::Class or zend_class_entry *, then this information will be used in ClassBase. One more way is to add new method extends to the Php::Class, for example:

Php::Class<SomeClass> someClass("SomeClass");
Php::Class<SomeChild> someChild("SomeChild");
someChild.extends(someClass);
// or alternative way
zend_class_entry *classEntry = zend_exception_get_default(TSRMLS_C);
someChild.extend(classEntry);

Interfaces can be implemented in the same way, by adding implements method to the Php::Class:

Php::Interface customInterface("CustomInterface");
Php::Class<SomeClass> someClass("SomeClass");
someClass.implements(spl_ce_Countable); // external zend_class_entry *
someClass.implements(customInterface); // explicit usage of Php::Interface for class

Thoughts?

Unable to load the compiled libphpcpp.so

System:

Linux 12.04 64 bit, 3.2.0-23 kernel
PHP: 5.5.9

Compilation seems OK, generated/installed libphpcpp.so in /usr/lib.

Copied the so into /usr/lib/php5/20121212, which is indicated by php.ini.

tryied to "php -i | grep libphpcpp" to see if the so lib is loaded and prompted:

PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) 'libphpcpp.so' in Unknown on line 0

Any steps I am missing here?

Make PHP functions accessible

It would be cool if all (or the most important) PHP functions are directly accessible as PHP-CPP functions. I am thinking about functions like

Php::call_user_func()
Php::count()
Php::isset()
Php::array_key_exists()
Php::strlen()

et cetera. This would make it much more easier to call PHP functions from within your own PHP-CPP extension. The only way to call PHP builtin functions now, is to store them in a Php::Value objects:

// how you can now call builtin PHP functions
Php::Value strlen("strlen");
Php::Value length = strlen("some-string");

// how it would be nicer:
Php::Value length = Php::call_user_func("strlen", "some-string");

// and how it would be really cool
Php::Value length = Php::strlen("some-string");

(Of course, this strlen() function is not so realistic, and you would probably be calling the C strlen version instead, but you get the idea).

This is a public issue. I will eventually solve this myself, but since my time is limited and this is an open source project, it would be cool if someone could help me with this.

Compiling errors with phpbrew's version

I'm trying to compile using a phpbrew version of PHP, and I'm getting this errors:

make                                                                                               drgomesp@MacBook-Pro-de-Daniel
g++ -Wall -c -I. -I/Users/drgomesp/.phpbrew/php/php-5.5.1/include/php -I/Users/drgomesp/.phpbrew/php/php-5.5.1/include/php/main -I/Users/drgomesp/.phpbrew/php/php-5.5.1/include/php/ext -I/Users/drgomesp/.phpbrew/php/php-5.5.1/include/php/Zend -I/Users/drgomesp/.phpbrew/php/php-5.5.1/include/php/TSRM -g -std=c++11 -fpic -o src/value.o src/value.cpp
src/value.cpp:690:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(const Value &value)        { return operator=(numericValue() % value.numericValue()); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:691:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(int16_t value)             { return operator=(numericValue() % value); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:692:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(int32_t value)             { return operator=(numericValue() % value); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:694:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(bool value)                { return operator=(numericValue() % value); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:695:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(char value)                { return operator=(numericValue() % value); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:696:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(const std::string &value)  { return operator=(numericValue() % atoi(value.c_str())); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:697:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(const char *value)         { return operator=(numericValue() % atoi(value)); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:698:62: error: call to member function 'operator=' is ambiguous
Value &Value::operator%=(double value)              { return operator=(numericValue() % (int)value); }
                                                             ^~~~~~~~~
src/value.cpp:469:15: note: candidate function
Value &Value::operator=(int16_t value)
              ^
src/value.cpp:489:15: note: candidate function
Value &Value::operator=(int32_t value)
              ^
src/value.cpp:509:15: note: candidate function
Value &Value::operator=(int64_t value)
              ^
src/value.cpp:529:15: note: candidate function
Value &Value::operator=(bool value)
              ^
src/value.cpp:549:15: note: candidate function
Value &Value::operator=(char value)
              ^
src/value.cpp:609:15: note: candidate function
Value &Value::operator=(double value)
              ^
src/value.cpp:332:15: note: candidate function
Value &Value::operator=(Value &&value)
              ^
src/value.cpp:402:15: note: candidate function
Value &Value::operator=(const Value &value)
              ^
src/value.cpp:449:15: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Value &Value::operator=(std::nullptr_t value)
              ^
src/value.cpp:569:15: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
Value &Value::operator=(const std::string &value)
              ^
src/value.cpp:589:15: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
Value &Value::operator=(const char *value)
              ^
src/value.cpp:765:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(const Value &value)          { return Value(numericValue() % value.numericValue()); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:766:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(int16_t value)               { return Value(numericValue() % value); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:767:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(int32_t value)               { return Value(numericValue() % value); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:769:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(bool value)                  { return Value(numericValue() % value); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:770:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(char value)                  { return Value(numericValue() % value); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:771:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(const std::string &value)    { return Value(numericValue() % atoi(value.c_str())); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:772:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(const char *value)           { return Value(numericValue() % atoi(value)); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
src/value.cpp:773:62: error: ambiguous conversion for functional-style cast from 'long' to 'Php::Value'
Value Value::operator%(double value)                { return Value(numericValue() % (int)value); }
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/value.cpp:58:8: note: candidate constructor
Value::Value(int16_t value)
       ^
src/value.cpp:69:8: note: candidate constructor
Value::Value(int32_t value)
       ^
src/value.cpp:80:8: note: candidate constructor
Value::Value(int64_t value)
       ^
src/value.cpp:91:8: note: candidate constructor
Value::Value(bool value)
       ^
src/value.cpp:102:8: note: candidate constructor
Value::Value(char value)
       ^
src/value.cpp:136:8: note: candidate constructor
Value::Value(double value)
       ^
src/value.cpp:208:8: note: candidate constructor
Value::Value(const Value &that)
       ^
src/value.cpp:265:8: note: candidate constructor
Value::Value(Value &&that)
       ^
In file included from src/value.cpp:27:
In file included from src/includes.h:89:
src/arithmetic.h:163:16: error: call to member function 'assign' is ambiguous
        return assign(value.numericValue());
               ^~~~~~
src/value.cpp:629:90: note: in instantiation of member function 'Php::Arithmetic<std::plus>::assign' requested here
Value &Value::operator+=(const Value &value)        { return Arithmetic<std::plus>(this).assign(value); }
                                                                                         ^
src/arithmetic.h:171:12: note: candidate function
    Value &assign(int16_t value)
           ^
src/arithmetic.h:185:12: note: candidate function
    Value &assign(int32_t value)
           ^
src/arithmetic.h:199:12: note: candidate function
    Value &assign(int64_t value)
           ^
src/arithmetic.h:213:12: note: candidate function
    Value &assign(bool value)
           ^
src/arithmetic.h:227:12: note: candidate function
    Value &assign(char value)
           ^
src/arithmetic.h:266:12: note: candidate function
    Value &assign(double value)
           ^
src/arithmetic.h:157:12: note: candidate function
    Value &assign(const Value &value)
           ^
src/arithmetic.h:244:12: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
    Value &assign(const std::string &value)
           ^
src/arithmetic.h:255:12: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
    Value &assign(const char *value)
           ^
src/arithmetic.h:177:24: error: call to member function 'operator=' is ambiguous
        return _value->operator=(F<long>()(_value->numericValue(), value));
               ~~~~~~~~^~~~~~~~~
src/value.cpp:630:90: note: in instantiation of member function 'Php::Arithmetic<std::plus>::assign' requested here
Value &Value::operator+=(int16_t value)             { return Arithmetic<std::plus>(this).assign(value); }
                                                                                         ^
src/../include/value.h:151:12: note: candidate function
    Value &operator=(int16_t value);
           ^
src/../include/value.h:152:12: note: candidate function
    Value &operator=(int32_t value);
           ^
src/../include/value.h:153:12: note: candidate function
    Value &operator=(int64_t value);
           ^
src/../include/value.h:154:12: note: candidate function
    Value &operator=(bool value);
           ^
src/../include/value.h:155:12: note: candidate function
    Value &operator=(char value);
           ^
src/../include/value.h:158:12: note: candidate function
    Value &operator=(double value);
           ^
src/../include/value.h:142:12: note: candidate function
    Value &operator=(Value &&value);
           ^
src/../include/value.h:150:12: note: candidate function
    Value &operator=(const Value &value);
           ^
src/../include/value.h:149:12: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
    Value &operator=(std::nullptr_t value);
           ^
src/../include/value.h:156:12: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
    Value &operator=(const std::string &value);
           ^
src/../include/value.h:157:12: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
    Value &operator=(const char *value);
           ^
In file included from src/value.cpp:27:
In file included from src/includes.h:89:
src/arithmetic.h:191:24: error: call to member function 'operator=' is ambiguous
        return _value->operator=(F<long>()(_value->numericValue(), value));
               ~~~~~~~~^~~~~~~~~
src/value.cpp:631:90: note: in instantiation of member function 'Php::Arithmetic<std::plus>::assign' requested here
Value &Value::operator+=(int32_t value)             { return Arithmetic<std::plus>(this).assign(value); }
                                                                                         ^
src/../include/value.h:151:12: note: candidate function
    Value &operator=(int16_t value);
           ^
src/../include/value.h:152:12: note: candidate function
    Value &operator=(int32_t value);
           ^
src/../include/value.h:153:12: note: candidate function
    Value &operator=(int64_t value);
           ^
src/../include/value.h:154:12: note: candidate function
    Value &operator=(bool value);
           ^
src/../include/value.h:155:12: note: candidate function
    Value &operator=(char value);
           ^
src/../include/value.h:158:12: note: candidate function
    Value &operator=(double value);
           ^
src/../include/value.h:142:12: note: candidate function
    Value &operator=(Value &&value);
           ^
src/../include/value.h:150:12: note: candidate function
    Value &operator=(const Value &value);
           ^
src/../include/value.h:149:12: note: candidate function not viable: no known conversion from 'long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
    Value &operator=(std::nullptr_t value);
           ^
src/../include/value.h:156:12: note: candidate function not viable: no known conversion from 'long' to 'const std::string' (aka 'const basic_string<char, char_traits<char>,
      allocator<char> >') for 1st argument
    Value &operator=(const std::string &value);
           ^
src/../include/value.h:157:12: note: candidate function not viable: no known conversion from 'long' to 'const char *' for 1st argument
    Value &operator=(const char *value);
           ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [src/value.o] Error 1

Implement SPL interfaces

We have just added the Php::Countable interface that can be implemented by your own class:

class MyClass : public Php::Base, public Php::Countable
{
public:
    virtual Php::Value count() override
    {
        return 12;
    }
};

If you make a class that extends from this Php::Countable "interface", your class is automatically converted into a PHP class that implements the built-in Countable interface from the SPL. In my opinion this is the most simple, most straight forward and most intuitive way to implement SPL interfaces, as the C++ code is almost identical to the PHP code that achieves the same.

There is however a drawback. In PHP it is possible to create an abstract class that implements the Countable interface, but that does not have an implementation for the count() method:

abstract class MyClass implements Countable
{
}

This would not be possible in C++. The compiler would always complain that an implementation for the count() method is missing. Is this a big problem? I think not, but I'd like to hear other arguments.

Further more, when you now implement the interface, the count() method is not yet automatically registered too. You still have to register this method by hand when you set up the Php::Extension object. This should not be necessary: implementing the interface should be enough. This should be fixed.

Once we have finished this Php::Countable interface, other SPL interfaces should be added too: Php::ArrayAccess, Php::Iterator, et cetera.

This is a public issue. I will eventually solve this myself, but since my time is limited and this is an open source project, it would be cool if someone could help me with this.

Compiling on OSX

Hi there,

I've managed to get PHP-CPP compiling and linking on OSX (10.9.2) targeting PHP5.5. Because it uses clang on OSX by default, there were some issues to be resolved with both compilation and linking. The Makefile is changed as well.

I will open a pull request tomorrow while I review and clean some things. This is just a heads up, so you'll know it is working. I cannot test is on Linux, since I don't have access to a Linux machine for now, so I don't know how GCC behaves on the changes. I;m fearing it will break the build.

Tomorrow I can access a Linux machine at work, so I can test it myself before opening a pull request, if it's desired.

Thanks!

Comments comments comments

Hey Emiel,

Sup sup,

I'd like to point out that whatever is going on here is probably not what should be happening. This, in fact, is happening on multiple places. There are tools to fix that for you.

I just thought I'd point this out, in case you'd forget.

More magic methods

Magic methods that still need to be implemented:

__construct()
__destruct()
__clone()
__callStatic()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.