Skip to content

Commit ce70162

Browse files
Merge branch 'master' of github.com:CopernicaMarketingSoftware/PHP-CPP
2 parents b7dcf19 + efed3ae commit ce70162

File tree

16 files changed

+428
-158
lines changed

16 files changed

+428
-158
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
*.txt
55
*.a.*
66
*.so.*
7+
shared/
8+
static/

.travis.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Although this is a C++ project, we use different PHP versions
2+
language: php
3+
4+
# we need bionic
5+
dist: trusty
6+
sudo: required
7+
group: edge
8+
9+
php:
10+
- 7.0
11+
- 7.1
12+
- 7.2
13+
- nightly # doesn't work yet on PHP 7.3! not building.
14+
15+
16+
# setting the env is the easiest, because it will mix with all the separate php versions (travis does this)
17+
env:
18+
- COMPILER_PKG=g++-4.8 COMPILER=g++-4.8
19+
- COMPILER_PKG=g++-4.9 COMPILER=g++-4.9
20+
- COMPILER_PKG=g++-5 COMPILER=g++-5
21+
- COMPILER_PKG=g++-6 COMPILER=g++-6
22+
- COMPILER_PKG=g++-7 COMPILER=g++-7
23+
- COMPILER_PKG=g++-8 COMPILER=g++-8
24+
- COMPILER_PKG=clang++-4 COMPILER=clang++-4.0
25+
- COMPILER_PKG=clang++-5 COMPILER=clang++-5.0
26+
- COMPILER_PKG=clang++-6 COMPILER=clang++-6.0
27+
28+
matrix:
29+
allow_failures:
30+
- php: nightly
31+
32+
before_install:
33+
# install access to all gcc compilers
34+
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
35+
36+
# and all relevant clang compilers
37+
- sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-4.0 main"
38+
- sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main"
39+
- sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main"
40+
41+
# update package index and install correct compiler
42+
- sudo apt-get -y update
43+
- sudo apt-get -y --allow-unauthenticated --no-install-recommends install ${COMPILER_PKG}
44+
45+
script:
46+
# simply make the project with the set compiler
47+
- make -j4 COMPILER=$COMPILER && sudo make install

Makefile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ INSTALL_LIB = ${INSTALL_PREFIX}/lib
4949
# Otherwise only release verions changes. (version is MAJOR.MINOR.RELEASE)
5050
#
5151

52-
SONAME = 2.0
53-
VERSION = 2.0.0
52+
SONAME = 2.1
53+
VERSION = 2.1.1
5454

5555

5656
#
@@ -117,8 +117,16 @@ PHP_COMPILER_FLAGS = ${COMPILER_FLAGS} `${PHP_CONFIG} --includes`
117117
#
118118

119119
LINKER_FLAGS = -shared
120-
PHP_LINKER_FLAGS = ${LINKER_FLAGS} `${PHP_CONFIG} --ldflags`
120+
ifeq ($(UNAME), Darwin)
121+
LINKER_FLAGS += -undefined dynamic_lookup
122+
endif
123+
PHP_LINKER_FLAGS = `${PHP_CONFIG} --ldflags` ${LINKER_FLAGS}
121124

125+
ifeq ($(UNAME), Darwin)
126+
LINKER_SONAME_OPTION = -install_name
127+
else
128+
LINKER_SONAME_OPTION = -soname
129+
endif
122130

123131
#
124132
# Command to remove files, copy files, link files and create directories.
@@ -183,7 +191,7 @@ phpcpp: ${PHP_SHARED_LIBRARY} ${PHP_STATIC_LIBRARY}
183191
@echo "Build complete."
184192

185193
${PHP_SHARED_LIBRARY}: shared_directories ${COMMON_SHARED_OBJECTS} ${PHP_SHARED_OBJECTS}
186-
${LINKER} ${PHP_LINKER_FLAGS} -Wl,-soname,libphpcpp.so.$(SONAME) -o $@ ${COMMON_SHARED_OBJECTS} ${PHP_SHARED_OBJECTS}
194+
${LINKER} ${PHP_LINKER_FLAGS} -Wl,${LINKER_SONAME_OPTION},libphpcpp.so.$(SONAME) -o $@ ${COMMON_SHARED_OBJECTS} ${PHP_SHARED_OBJECTS}
187195

188196
${PHP_STATIC_LIBRARY}: static_directories ${COMMON_STATIC_OBJECTS} ${PHP_STATIC_OBJECTS}
189197
${ARCHIVER} $@ ${COMMON_STATIC_OBJECTS} ${PHP_STATIC_OBJECTS}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
PHP-CPP
22
=======
33

4+
[![Build Status](https://travis-ci.org/CopernicaMarketingSoftware/PHP-CPP.svg?branch=master)](https://travis-ci.org/CopernicaMarketingSoftware/PHP-CPP)
5+
46
The PHP-CPP library is a C++ library for developing PHP extensions. It offers a collection
57
of well documented and easy-to-use classes that can be used and extended to build native
68
extensions for PHP. The full documentation can be found on http://www.php-cpp.com.

include/extension.h

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class PHPCPP_EXPORT Extension : public Namespace
8686
* @return Extension Same object to allow chaining
8787
*/
8888
Extension &onShutdown(const Callback &callback);
89-
89+
9090
/**
9191
* Register a callback that is called at the beginning of each pageview/request
9292
*
@@ -118,50 +118,27 @@ class PHPCPP_EXPORT Extension : public Namespace
118118
* @param ini The php.ini setting
119119
* @return Extension Same object to allow chaining
120120
*/
121-
Extension &add(Ini &&ini)
122-
{
123-
// skip when locked
124-
if (locked()) return *this;
125-
126-
// and add it to the list of classes
127-
_ini_entries.emplace_back(new Ini(std::move(ini)));
128-
129-
// allow chaining
130-
return *this;
131-
}
121+
Extension &add(Ini &&ini);
132122

133123
/**
134124
* Add a ini entry to the extension by copying it
135125
* @param ini The php.ini setting
136126
* @param Extension Same object to allow chaining
137127
*/
138-
Extension &add(const Ini &ini)
139-
{
140-
// skip when locked
141-
if (locked()) return *this;
142-
143-
// and add it to the list of classes
144-
_ini_entries.emplace_back(new Ini(ini));
145-
146-
// allow chaining
147-
return *this;
148-
}
128+
Extension &add(const Ini &ini);
149129

150130
/**
151131
* Because the add function exists in both the Namespace base class
152132
* as well as this extended Extension class, we have to tell the compiler
153-
* that the add methods from the base are accessible too
133+
* that the add methods from the base are accessble too
154134
*/
155135
using Namespace::add;
156-
136+
157137
/**
158138
* The total number of php.ini variables
159139
* @return size_t
160140
*/
161-
size_t iniVariables() const
162-
{
163-
return _ini_entries.size();
164-
}
141+
size_t iniVariables() const;
165142

166143
/**
167144
* Apply a callback to each php.ini variable
@@ -170,11 +147,7 @@ class PHPCPP_EXPORT Extension : public Namespace
170147
*
171148
* @param callback
172149
*/
173-
void iniVariables(const std::function<void(Ini &ini)> &callback)
174-
{
175-
// loop through the entries and apply the callback to each one
176-
for (auto ini : _ini_entries) callback(*ini);
177-
}
150+
void iniVariables(const std::function<void(Ini &ini)> &callback);
178151

179152
/**
180153
* Retrieve the module pointer
@@ -213,13 +186,6 @@ class PHPCPP_EXPORT Extension : public Namespace
213186
* @var std::unique_ptr<ExtensionImpl>
214187
*/
215188
std::unique_ptr<ExtensionImpl> _impl;
216-
217-
/**
218-
* Ini entry defined by the extension
219-
* @var list
220-
*/
221-
std::list<std::shared_ptr<Ini>> _ini_entries;
222-
223189
};
224190

225191
/**

include/value.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ class PHPCPP_EXPORT Value : private HashParent
398398
bool isBool() const;
399399
bool isString() const;
400400
bool isFloat() const;
401+
bool isReference() const;
401402
bool isObject() const;
402403
bool isArray() const;
403404
bool isScalar() const { return isNull() || isNumeric() || isBool() || isString() || isFloat(); }

zend/callable.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Implementation for the function class
55
*
66
* @author Emiel Bruijntjes <[email protected]>
7-
* @copyright 2013 Copernica BV
7+
* @copyright 2013 - 2019 Copernica BV
88
*/
99
#include "includes.h"
1010

@@ -27,11 +27,19 @@ void Callable::invoke(INTERNAL_FUNCTION_PARAMETERS)
2727
uint32_t argc = EX(func)->common.num_args;
2828
zend_arg_info* info = EX(func)->common.arg_info;
2929

30+
#if PHP_VERSION_ID < 70200
3031
// Sanity check
3132
assert(info[argc].class_name != nullptr && info[argc].name == nullptr);
3233

3334
// the callable we are retrieving
3435
Callable *callable = reinterpret_cast<Callable*>(info[argc].class_name);
36+
#else
37+
// Sanity check
38+
assert(info[argc].type != 0 && info[argc].name == nullptr);
39+
40+
// the callable we are retrieving
41+
Callable *callable = reinterpret_cast<Callable*>(info[argc].type);
42+
#endif
3543

3644
// check if sufficient parameters were passed (for some reason this check
3745
// is not done by Zend, so we do it here ourselves)
@@ -87,7 +95,15 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
8795
else
8896
{
8997
// install ourselves in the extra argument
98+
#if PHP_VERSION_ID < 70200
9099
_argv[_argc + 1].class_name = reinterpret_cast<const char*>(this);
100+
#else
101+
// @todo this is broken. the zend engine, from 7.2 onwards copies over
102+
// the struct and slices of the last element, because the num_args
103+
// is incorrect in their view. another place to put this may be
104+
// hiding it behind the fname
105+
_argv[_argc + 1].type = reinterpret_cast<zend_type>(this);
106+
#endif
91107

92108
// we use our own invoke method, which does a lookup
93109
// in the map we just installed ourselves in
@@ -111,21 +127,30 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
111127
*/
112128
void Callable::initialize(zend_internal_function_info *info, const char *classname) const
113129
{
130+
// initialize all common elements
131+
info->required_num_args = _required;
132+
info->return_reference = false;
133+
info->_is_variadic = false;
134+
135+
// the structure has been slightly altered since php7.2
136+
#if PHP_VERSION_ID < 70200
114137
// store the classname
115138
info->class_name = classname;
116139

117140
// number of required arguments, and the expected return type
118-
info->required_num_args = _required;
119141
info->type_hint = (unsigned char)_return;
120142

121-
// we do not support return-by-reference
122-
info->return_reference = false;
123-
124143
// since php 5.6 there are _allow_null and _is_variadic properties. It's
125144
// not exactly clear what they do (@todo find this out) so for now we set
126145
// them to false
127146
info->allow_null = false;
147+
#else
148+
// the properties that are available on php 7.2 and higher
149+
info->required_num_args = _required;
150+
info->return_reference = false;
128151
info->_is_variadic = false;
152+
info->type = ZEND_TYPE_ENCODE((int)_return, true);
153+
#endif
129154
}
130155

131156
/**

zend/callable.h

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* API.
66
*
77
* @author Emiel Bruijntjes <[email protected]>
8-
* @copyright 2013 Copernica BV
8+
* @copyright 2013 - 2019 Copernica BV
99
*/
1010

1111
/**
@@ -39,7 +39,7 @@ class Callable
3939
{
4040
// the first record is initialized with information about the function,
4141
// so we skip that here
42-
int i=1;
42+
int i = 1;
4343

4444
// loop through the arguments
4545
for (auto &argument : arguments)
@@ -51,9 +51,17 @@ class Callable
5151
fill(&_argv[i++], argument);
5252
}
5353

54-
// initialize the extra argument
54+
// initialize all elements to null
55+
_argv[i].name = nullptr;
56+
_argv[i].is_variadic = false;
57+
_argv[i].pass_by_reference = false;
58+
59+
// initialize the extra argument prior to 7.2
60+
#if PHP_VERSION_ID < 70200
5561
_argv[i].class_name = nullptr;
56-
_argv[i].name = nullptr;
62+
#else
63+
_argv[i].type = 0;
64+
#endif
5765
}
5866

5967
/**
@@ -104,7 +112,6 @@ class Callable
104112
/**
105113
* Fill a function entry
106114
* @param entry Entry to be filled
107-
* @param ns Active namespace
108115
* @param classname Optional class name
109116
* @param flags Access flags
110117
*/
@@ -113,7 +120,6 @@ class Callable
113120
/**
114121
* Fill function info
115122
* @param info Info object to be filled
116-
* @param ns Active namespace
117123
* @param classname Optional class name
118124
*/
119125
void initialize(zend_internal_function_info *info, const char *classname = nullptr) const;
@@ -167,13 +173,19 @@ class Callable
167173
// fill members
168174
info->name = arg.name();
169175

176+
#if PHP_VERSION_ID < 70200
170177
// are we filling an object
171178
if (arg.type() == Type::Object) info->class_name = arg.classname();
172179
else info->class_name = nullptr;
173180

181+
// whether or not we allow null
182+
info->allow_null = arg.allowNull();
183+
#endif
184+
174185
// set the correct type-hint
175186
switch (arg.type())
176187
{
188+
#if PHP_VERSION_ID < 70200
177189
case Type::Undefined: info->type_hint = IS_UNDEF; break; // undefined means we'll accept any type
178190
case Type::Null: info->type_hint = IS_UNDEF; break; // this is likely an error, what good would accepting NULL be? accept anything
179191
case Type::False: info->type_hint = _IS_BOOL; break; // accept true as well ;)
@@ -186,7 +198,23 @@ class Callable
186198
case Type::Object: info->type_hint = IS_OBJECT; break; // must be an object of the given classname
187199
case Type::Callable: info->type_hint = IS_CALLABLE; break; // anything that can be invoked
188200
default: info->type_hint = IS_UNDEF; break; // if not specified we allow anything
189-
201+
#else
202+
case Type::Undefined: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // undefined means we'll accept any type
203+
case Type::Null: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // this is likely an error, what good would accepting NULL be? accept anything
204+
case Type::False: info->type = ZEND_TYPE_ENCODE(_IS_BOOL, arg.allowNull()); break; // accept true as well ;)
205+
case Type::True: info->type = ZEND_TYPE_ENCODE(_IS_BOOL, arg.allowNull()); break; // accept false as well
206+
case Type::Bool: info->type = ZEND_TYPE_ENCODE(_IS_BOOL, arg.allowNull()); break; // any bool will do, true, false, the options are limitless
207+
case Type::Numeric: info->type = ZEND_TYPE_ENCODE(IS_LONG, arg.allowNull()); break; // accept integers here
208+
case Type::Float: info->type = ZEND_TYPE_ENCODE(IS_DOUBLE, arg.allowNull()); break; // floating-point values welcome too
209+
case Type::String: info->type = ZEND_TYPE_ENCODE(IS_STRING, arg.allowNull()); break; // accept strings, should auto-cast objects with __toString as well
210+
case Type::Array: info->type = ZEND_TYPE_ENCODE(IS_ARRAY, arg.allowNull()); break; // array of anything (individual members cannot be restricted)
211+
case Type::Object: // if there is a classname and the argument is not nullable, it's simply the classname
212+
if (!arg.classname()) info->type = ZEND_TYPE_ENCODE(IS_OBJECT, arg.allowNull());
213+
else info->type = ZEND_TYPE_ENCODE_CLASS(arg.classname(), arg.allowNull());
214+
break;
215+
case Type::Callable: info->type = ZEND_TYPE_ENCODE(IS_CALLABLE, arg.allowNull()); break; // anything that can be invoked
216+
default: info->type = ZEND_TYPE_ENCODE(IS_UNDEF, arg.allowNull()); break; // if not specified we allow anything
217+
#endif
190218
}
191219

192220
// from PHP 5.6 and onwards, an is_variadic property can be set, this
@@ -195,8 +223,7 @@ class Callable
195223
// support methods and functions with a fixed number of arguments.
196224
info->is_variadic = false;
197225

198-
// this parameter is a regular type
199-
info->allow_null = arg.allowNull();
226+
// whether or not to pass the argument by reference
200227
info->pass_by_reference = arg.byReference();
201228
}
202229

0 commit comments

Comments
 (0)