diff --git a/.gitignore b/.gitignore index 64fc9284..a165a4f3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ *.so.* shared/ static/ -.vscode/ \ No newline at end of file +.vscode/ +build/ +_output/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index be97069f..5ff51996 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,265 +1,261 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.0) - -PROJECT(phpcpp) - -# Use CMake File with following options -# PHPCPP_COMPILE_TS Set flag if PHP was compiled with thread safe -# PHPCPP_MSVCRT_STATIC Set flag if you want to compile the MSVC runtime as a static library -# PHPCPP_ARCH Set to "x86_64" if architecture and PHP was compiled under x64 or "x86" for 32 bit -# PHPCPP_PHP_PATH The path to PHP sources - -LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) - -IF(CMAKE_BUILD_TYPE MATCHES DEBUG) - ADD_DEFINITIONS(-DZEND_DEBUG=1) -ELSE() - ADD_DEFINITIONS(-DZEND_DEBUG=0) -ENDIF() - -IF (PHPCPP_COMPILE_TS) - ADD_DEFINITIONS(-DZTS) -ENDIF() - -ADD_DEFINITIONS(-D_MSC_STDINT_H_) -ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) -ADD_DEFINITIONS(-DBUILDING_PHPCPP) -ADD_DEFINITIONS(-DZEND_WIN32_KEEP_INLINE) - -IF (MSVC) - # Should compile MSVC runtime static or dll - IF (PHPCPP_MSVCRT_STATIC) - MESSAGE("Compile PHPCPP with static runtime") - - SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") - SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT") - - ELSE() - MESSAGE("Compile PHPCPP with dynamic runtime") - - SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") - SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD") - - ENDIF() - - IF (${PHPCPP_ARCH} STREQUAL "x86_64") - ADD_DEFINITIONS(-DPHP_WIN32 -DZEND_WIN32) - ELSE() - ADD_DEFINITIONS(-DPHP_WIN32 -DZEND_WIN32 -D_USE_32BIT_TIME_T) - ENDIF() - - SET(ADDITIONAL_COMPILER_FLAGS "/W3") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ADDITIONAL_COMPILER_FLAGS}") -ENDIF () - -INCLUDE_DIRECTORIES( - "${PHPCPP_PHP_PATH}/" - "${PHPCPP_PHP_PATH}/main" - "${PHPCPP_PHP_PATH}/Zend" - "${PHPCPP_PHP_PATH}/TSRM" - "${PHPCPP_PHP_PATH}/ext" - "${PHPCPP_PHP_PATH}/build/main" - "${PHPCPP_PHP_PATH}/build/Zend" -) -SET(PHP_LIBS "php") -SET(PHP_LIB_PATH "") - -IF (${PHPCPP_ARCH} STREQUAL "x86_64") - SET(PHP_LIB_PATH "x64/") -ENDIF() - -IF(CMAKE_BUILD_TYPE MATCHES DEBUG) - IF (PHPCPP_COMPILE_TS) - SET(PHP_LIBS ${PHP_LIBS} "php7ts_debug") - SET(PHP_LIB_PATH "${PHP_LIB_PATH}Debug_TS") - ELSE() - SET(PHP_LIBS ${PHP_LIBS} "php7_debug") - SET(PHP_LIB_PATH "${PHP_LIB_PATH}Debug") - ENDIF() -ELSE() - IF (PHPCPP_COMPILE_TS) - SET(PHP_LIBS ${PHP_LIBS} "php7ts") - SET(PHP_LIB_PATH "${PHP_LIB_PATH}Release_TS") - ELSE() - SET(PHP_LIBS ${PHP_LIBS} "php7") - SET(PHP_LIB_PATH "${PHP_LIB_PATH}Release") - ENDIF() -ENDIF() - -SET(PHPCPP_COMMON_SOURCES - common/modifiers.cpp - common/streambuf.cpp -) - -SET(PHPCPP_COMMON_HEADERS - common/extensionbase.h - common/includes.h - common/streambuf.h -) - -ADD_LIBRARY(phpcpp-common STATIC - ${PHPCPP_COMMON_HEADERS} - ${PHPCPP_COMMON_SOURCES} -) - -set_target_properties(phpcpp-common - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" -) - -SET(PHPCPP_ZEND_SOURCES - zend/base.cpp - zend/callable.cpp - zend/classbase.cpp - zend/classimpl.cpp - zend/constant.cpp - zend/constantfuncs.cpp - zend/eval.cpp - zend/exception_handler.cpp - zend/exists.cpp - zend/extension.cpp - zend/extensionimpl.cpp - # zend/fatalerror.cpp - zend/file.cpp - zend/function.cpp - zend/functor.cpp - zend/global.cpp - zend/globals.cpp - zend/hashmember.cpp - zend/ini.cpp - zend/inivalue.cpp - zend/iteratorimpl.cpp - zend/members.cpp - zend/module.cpp - zend/namespace.cpp - zend/object.cpp - zend/sapi.cpp - zend/script.cpp - zend/streambuf.cpp - zend/streams.cpp - zend/super.cpp - zend/value.cpp - zend/valueiterator.cpp - zend/zendcallable.cpp - zend/zval.cpp -) - -SET(PHPCPP_ZEND_HEADERS - zend/arithmetic.h - zend/boolmember.h - zend/callable.h - zend/classimpl.h - zend/compileroptions.h - zend/constantimpl.h - zend/delayedfree.h - zend/executestate.h - zend/extensionimpl.h - zend/extensionpath.h - zend/floatmember.h - zend/functor.h - zend/hashiterator.h - zend/includes.h - zend/init.h - zend/invaliditerator.h - zend/iteratorimpl.h - zend/lowercase.h - zend/member.h - zend/method.h - zend/module.h - zend/nativefunction.h - zend/notimplemented.h - zend/nullmember.h - zend/numericmember.h - zend/objectimpl.h - zend/opcodes.h - # zend/origexception.h - zend/parametersimpl.h - zend/property.h - zend/string.h - zend/stringmember.h - zend/symbol.h - zend/symbol.h - zend/traverseiterator.h - zend/valueiteratorimpl.h -) - -SET(PHPCPP_HEADERS_INCLUDE - include/argument.h - include/array.h - include/arrayaccess.h - include/base.h - include/byref.h - include/byval.h - include/call.h - include/class.h - include/classbase.h - include/classtype.h - include/constant.h - include/countable.h - include/deprecated.h - include/error.h - include/exception.h - include/extension.h - # include/fatalerror.h - include/file.h - include/function.h - include/global.h - include/globals.h - include/hashmember.h - include/hashparent.h - include/ini.h - include/inivalue.h - include/interface.h - include/iterator.h - include/modifiers.h - include/namespace.h - include/noexcept.h - include/object.h - include/parameters.h - include/platform.h - include/script.h - include/serializable.h - include/streams.h - include/super.h - include/thread_local.h - include/traversable.h - include/type.h - include/value.h - include/valueiterator.h - include/version.h - include/visibility.h - include/zendcallable.h - include/zval.h -) - -LINK_DIRECTORIES(${PHP_LIB_PATH}) - -IF (PHPCPP_SHARED) - ADD_LIBRARY(phpcpp SHARED - ${PHPCPP_HEADERS_INCLUDE} - ${PHPCPP_ZEND_HEADERS} - ${PHPCPP_ZEND_SOURCES} - phpcpp.h - ) - - TARGET_LINK_LIBRARIES(phpcpp phpcpp-common ${PHP_LIBS}) -ELSE() - ADD_LIBRARY(phpcpp STATIC - ${PHPCPP_HEADERS_INCLUDE} - ${PHPCPP_ZEND_HEADERS} - ${PHPCPP_ZEND_SOURCES} - phpcpp.h - ) - - TARGET_LINK_LIBRARIES(phpcpp STATIC phpcpp-common ${PHP_LIBS}) -ENDIF() - -SET_TARGET_PROPERTIES(phpcpp - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" -) +cmake_minimum_required(VERSION 3.11-3.18) + +set(PHPCPP_VERSION 2.3.5) +project(phpcpp VERSION ${PHPCPP_VERSION} LANGUAGES CXX) + + +# ----------------------------------------------------------------------------- +# Configurable options +# +# Uncomment and set the value, or set directly with cmake +# ----------------------------------------------------------------------------- +#set(PHPCPP_BUILD_SHARED TRUE) # Build static or shared library +#set(PHPCPP_BUILD_EXAMPLES TRUE) # Build example extensions +#set(PHPCPP_INSTALL TRUE) # Generate install target + +# On Linux, uncomment to set different php-config filename +#set(PHP_CONFIG_FILENAME "php-config") + +# Options for building on Windows with MSVC +# ----------------------------------------------------------------------------- +# PHP devel pack dir, download from https://windows.php.net/download/ +#set(PHP_DEV_DIR "d:/dev/cpp_php/ts/php-7.4.30-devel-vc15-x64") +# Set to TRUE if PHP was compiled with thread safe +#set(PHPCPP_COMPILE_TS TRUE) +# Set to "x86_64" if architecture and PHP was compiled under x64 or "x86" for 32 bit +#set(PHPCPP_ARCH "x86_64") + + + +# ----------------------------------------------------------------------------- +# Default values +# ----------------------------------------------------------------------------- +# Build static or shared library +if(NOT DEFINED PHPCPP_BUILD_SHARED) + set(PHPCPP_BUILD_SHARED TRUE) +endif() + +# Build example extensions +if(NOT DEFINED PHPCPP_BUILD_EXAMPLES) + set(PHPCPP_BUILD_EXAMPLES TRUE) +endif() + +# Generate library install target +if(NOT DEFINED PHPCPP_INSTALL) + set(PHPCPP_INSTALL TRUE) +endif() + + +if(PHPCPP_BUILD_SHARED) + message(STATUS "Build PHP-CPP ${PHPCPP_VERSION} shared library...") +else() + message(STATUS "Build PHP-CPP ${PHPCPP_VERSION} static library...") +endif() + + +if(WIN32) + # Windows build options + if(NOT DEFINED PHP_DEV_DIR) + message(FATAL_ERROR "PHP development dir variable PHP_DEV_DIR not defined!") + endif() + + if(NOT DEFINED PHPCPP_COMPILE_TS) + message(FATAL_ERROR "PHP threading(TS/NTS) variable PHPCPP_COMPILE_TS not defined!") + endif() + + if(NOT DEFINED PHPCPP_ARCH) + message(FATAL_ERROR "PHP architecture variable PHPCPP_ARCH not defined!") + endif() + + # PHP library dir + set(PHP_LIB_DIR "${PHP_DEV_DIR}/lib") + # PHP library file name + set(PHP_LIB_NAME "php7ts") + if(NOT PHPCPP_COMPILE_TS) + set(PHP_LIB_NAME "php7") + endif() + + message(STATUS "PHP_LIB_DIR ${PHP_LIB_DIR}") + message(STATUS "PHPCPP_ARCH ${PHPCPP_ARCH}") + message(STATUS "PHPCPP_COMPILE_TS ${PHPCPP_COMPILE_TS}") + +else() + # Non windows, try detect php with php-config + include(cmake/utils.cmake) + + if(NOT DEFINED PHP_CONFIG_FILENAME) + find_php_dev(php-config) # use default php-config + else() + find_php_dev(${PHP_CONFIG_FILENAME}) + endif() + + if(NOT PHP_DEV_FOUND) + message(FATAL_ERROR "PHP development not found!") + endif() + + if(PHP_VERSION_NUMBER LESS 70000) + message(FATAL_ERROR "PHP-CPP works only with PHP 7") + endif() + + message(STATUS "PHP_VERSION ${PHP_VERSION}") + include(GNUInstallDirs) +endif() + + +# Miscs php-cpp variables +# ----------------------------------------------------------------------------- +set(PHPCPP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) +message(STATUS "PHPCPP_SOURCE_DIR ${PHPCPP_SOURCE_DIR}") + +if(PHPCPP_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + # we are master project + set(PHPCPP_OUTPUT_DIR ${PHPCPP_SOURCE_DIR}/_output) +else() + set(PHPCPP_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/_output) +endif() + + +# Include headers and sources list +include(cmake/sources.cmake) + + +# phpcpp-common +# ----------------------------------------------------------------------------- +add_library(phpcpp-common STATIC) + +target_sources(phpcpp-common + PUBLIC ${PHPCPP_COMMON_HEADERS} + PRIVATE ${PHPCPP_COMMON_SOURCES} ) + +if(WIN32) + target_include_directories(phpcpp-common + PUBLIC ${PHP_DEV_DIR}/include + PUBLIC ${PHP_DEV_DIR}/include/main + PUBLIC ${PHP_DEV_DIR}/include/Zend + PUBLIC ${PHP_DEV_DIR}/include/TSRM + PUBLIC ${PHP_DEV_DIR}/include/ext ) + + #target_compile_definitions(phpcpp-common + # PUBLIC $<$:ZEND_DEBUG=1>$<$:ZEND_DEBUG=0> ) + # Always use PHP release build + target_compile_definitions(phpcpp-common PUBLIC ZEND_DEBUG=0 ) + + if(PHPCPP_COMPILE_TS) + target_compile_definitions(phpcpp-common PUBLIC ZTS ) + endif() + + if("x86" STREQUAL ${PHPCPP_ARCH}) + target_compile_definitions(phpcpp-common PUBLIC _USE_32BIT_TIME_T ) + endif() + + target_compile_definitions(phpcpp-common + PUBLIC PHP_WIN32 + PUBLIC ZEND_WIN32 + PUBLIC ZEND_WIN32_KEEP_INLINE ) + + if(MSVC) + target_compile_definitions(phpcpp-common + PUBLIC _MSC_STDINT_H_ + PUBLIC _CRT_SECURE_NO_WARNINGS + PRIVATE W3 ) + endif() + +else() # not win32 + target_compile_definitions(phpcpp-common PRIVATE BUILDING_PHPCPP) + target_compile_options(phpcpp-common PRIVATE -fpic -c -fvisibility=hidden -Wno-write-strings -MD -Wall ) + target_include_directories(phpcpp-common PUBLIC ${PHP_INCLUDE_DIRS}) +endif() + +target_compile_features(phpcpp-common PRIVATE cxx_std_11) + + +# phpcpp library +# ----------------------------------------------------------------------------- +if(PHPCPP_BUILD_SHARED) + add_library(phpcpp SHARED) + if(NOT MSVC) + target_link_options(phpcpp PRIVATE -shared ${PHP_LDFLAGS}) + endif() +else() + add_library(phpcpp STATIC) +endif() + +target_link_libraries(phpcpp PRIVATE phpcpp-common) + +if(WIN32) + if(PHPCPP_BUILD_SHARED) + target_compile_definitions(phpcpp PRIVATE BUILDING_PHPCPP) + endif() + target_link_directories(phpcpp PUBLIC ${PHP_LIB_DIR}) + target_link_libraries(phpcpp PUBLIC ${PHP_LIB_NAME} ) +else() + target_compile_definitions(phpcpp PRIVATE BUILDING_PHPCPP) + target_compile_options(phpcpp PRIVATE -fpic -c -fvisibility=hidden -Wno-write-strings -MD -Wall ) +endif() + +target_sources(phpcpp + PRIVATE ${PHPCPP_HEADERS_FILES} + PRIVATE ${PHPCPP_ZEND_HEADERS} + PRIVATE ${PHPCPP_ZEND_SOURCES} ) + +target_compile_features(phpcpp PRIVATE cxx_std_11 ) + + +# Prepare phpcpp header files for dependend projects and building examples +# publish PHPCPP_INCLUDE_DIR variable to outside world +# ----------------------------------------------------------------------------- +set(PHPCPP_INCLUDE_DIR "${CMAKE_BINARY_DIR}/phpcpp_include") +file(COPY phpcpp.h DESTINATION ${PHPCPP_INCLUDE_DIR}) +file(COPY include/ DESTINATION ${PHPCPP_INCLUDE_DIR}/phpcpp) + +if(NOT PHPCPP_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(PHPCPP_INCLUDE_DIR ${PHPCPP_INCLUDE_DIR} PARENT_SCOPE) +endif() +message(STATUS "PHPCPP_INCLUDE_DIR ${PHPCPP_INCLUDE_DIR}") + + +# Build examples +#----------------------------------------------------------------------------- +if(PHPCPP_BUILD_EXAMPLES) + message(STATUS "Generating examples") + add_subdirectory(Examples) +endif() + + +# Install +# ----------------------------------------------------------------------------- +if(PHPCPP_INSTALL) + message(STATUS "Generating install") + install(FILES phpcpp.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/") + install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/phpcpp/") + + install( TARGETS phpcpp-common phpcpp + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +endif() + + +# Copy binaries, resources to _output folder +# ----------------------------------------------------------------------------- +set(OUTPUT_LIBDIR "${PHPCPP_OUTPUT_DIR}/lib_static") +if (PHPCPP_BUILD_SHARED) + set(OUTPUT_LIBDIR "${PHPCPP_OUTPUT_DIR}/lib_shared") +endif() + +# Copy build output dir to _output dir +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT_LIBDIR}/$<$:debug>$<$:release> + COMMAND ${CMAKE_COMMAND} -E copy $ ${OUTPUT_LIBDIR}/$<$:debug>$<$:release> + COMMAND ${CMAKE_COMMAND} -E copy $ ${OUTPUT_LIBDIR}/$<$:debug>$<$:release> ) + +if(WIN32 AND PHPCPP_BUILD_SHARED) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${OUTPUT_LIBDIR}/$<$:debug>$<$:release>) +endif() + +# Copy headers to _output dir +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include ${PHPCPP_OUTPUT_DIR}/include/phpcpp ) + +# Copy phpcpp.h to _output dir +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/phpcpp.h ${PHPCPP_OUTPUT_DIR}/include ) \ No newline at end of file diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt new file mode 100644 index 00000000..5a1a158b --- /dev/null +++ b/Examples/CMakeLists.txt @@ -0,0 +1,17 @@ +project(sample) + +add_subdirectory(CallPhpFunctions) +#add_subdirectory(ConstStaticProp) +add_subdirectory(CppClassesInPhp) +add_subdirectory(DlUnrestricted) +add_subdirectory(EmptyExtension) +add_subdirectory(Exceptions/ExceptionCatch) +add_subdirectory(Exceptions/ExceptionThrow) +add_subdirectory(Extension) +add_subdirectory(FunctionNoParameters) +add_subdirectory(FunctionReturnValue) +add_subdirectory(FunctionVoid) +add_subdirectory(FunctionWithParameters) +add_subdirectory(Globals) +add_subdirectory(ReturnObject) +add_subdirectory(simple) \ No newline at end of file diff --git a/Examples/CallPhpFunctions/CMakeLists.txt b/Examples/CallPhpFunctions/CMakeLists.txt new file mode 100644 index 00000000..63225568 --- /dev/null +++ b/Examples/CallPhpFunctions/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "callphpfunction" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/CallPhpFunctions/callphpfunction.cpp b/Examples/CallPhpFunctions/callphpfunction.cpp index db112c7a..5f36001f 100644 --- a/Examples/CallPhpFunctions/callphpfunction.cpp +++ b/Examples/CallPhpFunctions/callphpfunction.cpp @@ -1,7 +1,7 @@ /** * callphpfunction.cpp * @author Jasper van Eck - * + * * An example file to show the working of a php function call in C++. */ @@ -26,27 +26,29 @@ Php::Value call_php_function(Php::Parameters ¶ms) { // check whether the parameter is callable if (!params[0].isCallable()) throw Php::Exception("Not a callable type."); - + // perform the callback return params[0](1,2,3); } // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("call_php_function","1.0"); - + // add function to extension - extension.add("call_php_function", { - Php::ByVal("addFunc", Php::Type::Callable), - Php::ByVal("x", Php::Type::Numeric) + extension.add("call_php_function", + &Php::ZendCallable::invoke, + { + Php::ByVal("addFunc", Php::Type::Callable), + Php::ByVal("x", Php::Type::Numeric) }); - + // return the extension module return extension.module(); } diff --git a/Examples/ConstStaticProp/CMakeLists.txt b/Examples/ConstStaticProp/CMakeLists.txt new file mode 100644 index 00000000..d0cae5bd --- /dev/null +++ b/Examples/ConstStaticProp/CMakeLists.txt @@ -0,0 +1,5 @@ +set(SAMPLE_NAME "conststaticprop" ) +set(SAMPLE_SOURCES cpp/mytestext.cpp cpp/mytestext.h) +set(SAMPLE_PHPFILE test.php) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/ConstStaticProp/cpp/mytestext.cpp b/Examples/ConstStaticProp/cpp/mytestext.cpp index 7b5d0cec..f74da7f9 100644 --- a/Examples/ConstStaticProp/cpp/mytestext.cpp +++ b/Examples/ConstStaticProp/cpp/mytestext.cpp @@ -29,7 +29,7 @@ class MyTestExt : public Php::Base extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_test_ext","0.1a"); diff --git a/Examples/CppClassesInPhp/CMakeLists.txt b/Examples/CppClassesInPhp/CMakeLists.txt new file mode 100644 index 00000000..a484d98c --- /dev/null +++ b/Examples/CppClassesInPhp/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "cppclassinphp" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/CppClassesInPhp/cppclassinphp.cpp b/Examples/CppClassesInPhp/cppclassinphp.cpp index 22ed4b81..79eacbb5 100644 --- a/Examples/CppClassesInPhp/cppclassinphp.cpp +++ b/Examples/CppClassesInPhp/cppclassinphp.cpp @@ -1,7 +1,7 @@ /** * cppclassinphp.cpp * @author Jasper van Eck - * + * * An example file to show the working of using a C++ class in PHP. */ @@ -15,7 +15,7 @@ class MyCustomClass : public Php::Base // , public Php::Countable { private: int _x = 3; - + public: MyCustomClass() { @@ -31,7 +31,7 @@ class MyCustomClass : public Php::Base // , public Php::Countable { std::cout << "MyCustomClass::MyCustomClass copy constructor" << std::endl; } - + virtual ~MyCustomClass() { std::cout << "MyCustomClass::~MyCustomClass" << std::endl; @@ -46,7 +46,7 @@ class MyCustomClass : public Php::Base // , public Php::Countable { std::cout << "MyCustomClass::__destruct" << std::endl; } - + virtual Php::Value count() //override { return 33; @@ -62,12 +62,12 @@ class MyCustomClass : public Php::Base // , public Php::Countable std::cout << "key: " << i.first << " \t\tval: " << i.second << std::endl; } } - + Php::Value myMethod(Php::Parameters ¶ms) { // check number of parameters if (params.size() != 1) throw Php::Exception("Invalid number of parameters supplied"); - + std::cout << "myMethod is called for object " << _x << std::endl; std::cout << "property1: " << property("property1") << std::endl; @@ -84,23 +84,23 @@ class MyCustomClass : public Php::Base // , public Php::Countable // show it std::cout << "current time: " << now.call("format", "Y-m-d H:i:s") << std::endl; - + std::cout << "construct " << params[0] << std::endl; // construct a new class Php::Object obj(params[0]); std::cout << "return " << params[0] << std::endl; - - - - + + + + // return it return obj; - - + + // std::cout << "get property1 " << value()["property1"] << std::endl; - // + // // // set it to something else // value().set("property1", "new value"); // @@ -109,27 +109,27 @@ class MyCustomClass : public Php::Base // , public Php::Countable }; // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("Cpp_classes_in_php","1.0"); - + // build an interface Php::Interface interface("MyInterface"); - + // add methods to the interface interface.method("method1"); interface.method("method2"); - + // add the interface to the extension extension.add(interface); - + // we are going to define a class Php::Class customClass("MyClass"); - + // add methods to it customClass.method<&MyCustomClass::myMethod>("myMethod", Php::Final, {}); customClass.method<&MyCustomClass::myMethod>("myMethod2"); @@ -142,10 +142,10 @@ extern "C" customClass.method<&MyCustomClass::loop>("loopObject", { Php::ByVal("obj", Php::Type::Object) }); - + // add the class to the extension extension.add(customClass); - + // return the extension module return extension; } diff --git a/Examples/DlUnrestricted/CMakeLists.txt b/Examples/DlUnrestricted/CMakeLists.txt new file mode 100644 index 00000000..a7aaad86 --- /dev/null +++ b/Examples/DlUnrestricted/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "dlunrestricted" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/DlUnrestricted/dlunrestricted.cpp b/Examples/DlUnrestricted/dlunrestricted.cpp index a64c1188..3efa9fac 100644 --- a/Examples/DlUnrestricted/dlunrestricted.cpp +++ b/Examples/DlUnrestricted/dlunrestricted.cpp @@ -1,24 +1,25 @@ /** - * functionvoid.cpp + * dlunrestricted.cpp * @author Jasper van Eck - * + * * An example file to show the working of a void function call. */ /** * Libraries used. */ +#include #include /** * Function to load every possible extension by pathname * - * It takes one argument: the filename of the PHP extension, and returns a + * It takes one argument: the filename of the PHP extension, and returns a * boolean to indicate whether the extension was correctly loaded. * * This function goes further than the original PHP dl() fuction, because * it does not check whether the passed in extension object is stored in the - * right directory. Literally every possible extension, also local ones + * right directory. Literally every possible extension, also local ones * created by end users, can be loaded. * * @param params Vector of parameters @@ -28,35 +29,34 @@ Php::Value dl_unrestricted(Php::Parameters ¶ms) { // get extension name std::string pathname = params[0]; - + // should it be opened persistently? bool persistent = params.size() > 1 ? params[1].boolValue() : false; - + // load the extension return Php::dl(pathname, persistent); } - + /** * Switch to C context to ensure that the get_module() function * is callable by C programs (which the Zend engine is) */ extern "C" { /** - * Startup function that is called by the Zend engine + * Startup function that is called by the Zend engine * to retrieve all information about the extension * @return void* */ - PHPCPP_EXPORT void *get_module() { + MODULE_EXPORT void *get_module() { // create static instance of the extension object static Php::Extension myExtension("dl_unrestricted", "1.0"); - + // the extension has one method myExtension.add("dl_unrestricted", { Php::ByVal("pathname", Php::Type::String) }); - + // return the extension return myExtension; } } - diff --git a/Examples/EmptyExtension/CMakeLists.txt b/Examples/EmptyExtension/CMakeLists.txt new file mode 100644 index 00000000..e35a9ac5 --- /dev/null +++ b/Examples/EmptyExtension/CMakeLists.txt @@ -0,0 +1,4 @@ +set(SAMPLE_NAME "emptyextension" ) +set(SAMPLE_SOURCES main.cpp) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/EmptyExtension/main.cpp b/Examples/EmptyExtension/main.cpp index b4c44262..83d606e7 100644 --- a/Examples/EmptyExtension/main.cpp +++ b/Examples/EmptyExtension/main.cpp @@ -1,10 +1,11 @@ +#include #include /** * tell the compiler that the get_module is a pure C function */ extern "C" { - + /** * Function that is called by PHP right after the PHP process * has started, and that returns an address of an internal PHP @@ -12,14 +13,14 @@ extern "C" { * * @return void* a pointer to an address that is understood by PHP */ - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // static(!) Php::Extension object that should stay in memory // for the entire duration of the process (that's why it's static) static Php::Extension extension("yourextension", "1.0"); - + // @todo add your own functions, classes, namespaces to the extension - + // return the extension return extension; } diff --git a/Examples/Exceptions/ExceptionCatch/CMakeLists.txt b/Examples/Exceptions/ExceptionCatch/CMakeLists.txt new file mode 100644 index 00000000..eecd04b8 --- /dev/null +++ b/Examples/Exceptions/ExceptionCatch/CMakeLists.txt @@ -0,0 +1,5 @@ +set(SAMPLE_NAME "exceptioncatch" ) +set(SAMPLE_SOURCES exceptionCatch.cpp) +set(SAMPLE_PHPFILE exception.php) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp b/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp index 9168d47f..56706be2 100644 --- a/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp +++ b/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp @@ -1,9 +1,9 @@ /** * exception.cpp * @author Jasper van Eck - * - * An example file to show the working of a C++ function that - * takes a callback function as parameter, and handles the + * + * An example file to show the working of a C++ function that + * takes a callback function as parameter, and handles the * exception thrown by the callback function. */ @@ -31,7 +31,7 @@ void my_catch_exception_function(Php::Parameters ¶ms) // this must be a callable type if (!callback.isCallable()) throw Php::Exception("Parameter 0 is not a function"); - // we're going to call a function that could throw an exception, start a + // we're going to call a function that could throw an exception, start a // try-catch block to deal with that try { @@ -47,17 +47,18 @@ void my_catch_exception_function(Php::Parameters ¶ms) // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_exception_catch","1.0"); - + // add function to extension - extension.add("my_catch_exception_function"); - + extension.add("my_catch_exception_function", + &Php::ZendCallable::invoke); + // return the extension module return extension.module(); } diff --git a/Examples/Exceptions/ExceptionThrow/CMakeLists.txt b/Examples/Exceptions/ExceptionThrow/CMakeLists.txt new file mode 100644 index 00000000..6af90dbd --- /dev/null +++ b/Examples/Exceptions/ExceptionThrow/CMakeLists.txt @@ -0,0 +1,5 @@ +set(SAMPLE_NAME "exceptionthrow" ) +set(SAMPLE_SOURCES exceptionThrow.cpp) +set(SAMPLE_PHPFILE exception.php) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/Exceptions/ExceptionThrow/exceptionThrow.cpp b/Examples/Exceptions/ExceptionThrow/exceptionThrow.cpp index 998ea0d3..573a802d 100644 --- a/Examples/Exceptions/ExceptionThrow/exceptionThrow.cpp +++ b/Examples/Exceptions/ExceptionThrow/exceptionThrow.cpp @@ -1,15 +1,16 @@ /** * exception.cpp * @author Jasper van Eck - * - * An example file to show the working of a C++ function that + * + * An example file to show the working of a C++ function that * throws an exception, which can be caught by PHP. - * + * */ /** * Libraries used. */ +#include #include /** @@ -28,17 +29,18 @@ void my_throw_exception_function() // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_exception_throw","1.0"); - + // add function to extension - extension.add("my_throw_exception_function"); - + extension.add("my_throw_exception_function", + &Php::ZendCallable::invoke); + // return the extension module return extension.module(); } diff --git a/Examples/Extension/CMakeLists.txt b/Examples/Extension/CMakeLists.txt new file mode 100644 index 00000000..215a4cbf --- /dev/null +++ b/Examples/Extension/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "extension" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/Extension/extension.cpp b/Examples/Extension/extension.cpp index 99da5c73..bd75e7dd 100644 --- a/Examples/Extension/extension.cpp +++ b/Examples/Extension/extension.cpp @@ -1,10 +1,11 @@ /** * extension.cpp * @author Jasper van Eck - * + * * An example file to show the working of an extension. */ // library include +#include #include /** @@ -13,14 +14,14 @@ using namespace std; // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_simple_extension","1.0"); - + // return the extension module return extension.module(); } diff --git a/Examples/FunctionNoParameters/CMakeLists.txt b/Examples/FunctionNoParameters/CMakeLists.txt new file mode 100644 index 00000000..3569a15a --- /dev/null +++ b/Examples/FunctionNoParameters/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "functionnoparameters" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/FunctionNoParameters/functionnoparameters.cpp b/Examples/FunctionNoParameters/functionnoparameters.cpp index 56ddff07..4661e863 100644 --- a/Examples/FunctionNoParameters/functionnoparameters.cpp +++ b/Examples/FunctionNoParameters/functionnoparameters.cpp @@ -1,13 +1,14 @@ /** * functionnoparameters.cpp * @author Jasper van Eck - * + * * An example file to show the working of a function call without parameters. */ /** * Libraries used. */ +#include #include /** @@ -26,17 +27,18 @@ Php::Value my_no_parameters_function() // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_function_no_parameters","1.0"); - + // add function to extension - extension.add("my_no_parameters_function"); - + extension.add("my_no_parameters_function", + &Php::ZendCallable::invoke); + // return the extension module return extension.module(); } diff --git a/Examples/FunctionReturnValue/CMakeLists.txt b/Examples/FunctionReturnValue/CMakeLists.txt new file mode 100644 index 00000000..195a7aa4 --- /dev/null +++ b/Examples/FunctionReturnValue/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "functionreturnvalue" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/FunctionReturnValue/functionreturnvalue.cpp b/Examples/FunctionReturnValue/functionreturnvalue.cpp index 5d2c0064..d8ae07aa 100644 --- a/Examples/FunctionReturnValue/functionreturnvalue.cpp +++ b/Examples/FunctionReturnValue/functionreturnvalue.cpp @@ -1,13 +1,14 @@ /** * functionreturnvalue.cpp * @author Jasper van Eck - * + * * An example file to show the working of a function call with a return value. */ /** * Libraries used. */ +#include #include /** @@ -26,17 +27,18 @@ Php::Value my_return_value_function() // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_function_return_value","1.0"); - + // add function to extension - extension.add("my_return_value_function"); - + extension.add("my_return_value_function", + &Php::ZendCallable::invoke); + // return the extension module return extension.module(); } diff --git a/Examples/FunctionVoid/CMakeLists.txt b/Examples/FunctionVoid/CMakeLists.txt new file mode 100644 index 00000000..bf3b2669 --- /dev/null +++ b/Examples/FunctionVoid/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "functionvoid" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/FunctionVoid/functionvoid.cpp b/Examples/FunctionVoid/functionvoid.cpp index e2a3768b..c7313d1d 100644 --- a/Examples/FunctionVoid/functionvoid.cpp +++ b/Examples/FunctionVoid/functionvoid.cpp @@ -1,7 +1,7 @@ /** * functionvoid.cpp * @author Jasper van Eck - * + * * An example file to show the working of a void function call. */ @@ -26,17 +26,17 @@ void my_function_void() // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("my_function_void","1.0"); - + // add function to extension - extension.add("my_void_function"); - + extension.add("my_void_function", + &Php::ZendCallable::invoke); // return the extension module return extension.module(); } diff --git a/Examples/FunctionWithParameters/CMakeLists.txt b/Examples/FunctionWithParameters/CMakeLists.txt new file mode 100644 index 00000000..25f41b76 --- /dev/null +++ b/Examples/FunctionWithParameters/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "functionwithparameters" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/FunctionWithParameters/functionwithparameters.cpp b/Examples/FunctionWithParameters/functionwithparameters.cpp index 12fed943..5730684f 100644 --- a/Examples/FunctionWithParameters/functionwithparameters.cpp +++ b/Examples/FunctionWithParameters/functionwithparameters.cpp @@ -1,14 +1,14 @@ /** * functionwithparameters.cpp * @author Jasper van Eck - * + * * An example file to show the working of a function call with parameters. */ /** * Default Cpp libraries */ - + #include #include @@ -45,7 +45,7 @@ Php::Value my_with_defined_parameters_function(Php::Parameters ¶ms) { cout << "Parameter " << i << ": " << params[i] << endl; } - + return params[0] + params[1]; } @@ -86,38 +86,47 @@ void my_with_defined_object_parameters_function(Php::Parameters ¶ms) } // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension - static Php::Extension extension("my_function_with_parameters","1.0"); - + static Php::Extension extension("my_function_with_parameters", "1.0"); + // add function, with undefined parameters, to extension - extension.add("my_with_undefined_parameters_function"); - + extension.add("my_with_undefined_parameters_function", + &Php::ZendCallable::invoke); + // add function, with defined numeric parameters, to extension - extension.add("my_with_defined_parameters_function", { - Php::ByVal("x", Php::Type::Numeric), - Php::ByVal("y", Php::Type::Numeric) + extension.add("my_with_defined_parameters_function", + &Php::ZendCallable::invoke, + { + Php::ByVal("x", Php::Type::Numeric), + Php::ByVal("y", Php::Type::Numeric) }); - + // add function, with defined parameter by reference, to extension - extension.add("my_with_defined_parameters_reference_function", { - Php::ByRef("string", Php::Type::String) + extension.add("my_with_defined_parameters_reference_function", + &Php::ZendCallable::invoke, + { + Php::ByRef("string", Php::Type::String) }); - + // add function, with defined array parameter, to extension - extension.add("my_with_defined_array_parameters_function", { - Php::ByVal("array", Php::Type::Array) + extension.add("my_with_defined_array_parameters_function", + &Php::ZendCallable::invoke, + { + Php::ByVal("array", Php::Type::Array) }); - + // add function, with defined object parameter, to extension - extension.add("my_with_defined_object_parameters_function", { - Php::ByVal("myClassObjVar", "MyPhpClass") + extension.add("my_with_defined_object_parameters_function", + &Php::ZendCallable::invoke, + { + Php::ByVal("myClassObjVar", "MyPhpClass") }); - + // return the extension module return extension.module(); } diff --git a/Examples/Globals/CMakeLists.txt b/Examples/Globals/CMakeLists.txt new file mode 100644 index 00000000..e6ff2d07 --- /dev/null +++ b/Examples/Globals/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "globals" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/Globals/globals.cpp b/Examples/Globals/globals.cpp index 1812acf3..75439fdc 100644 --- a/Examples/Globals/globals.cpp +++ b/Examples/Globals/globals.cpp @@ -1,7 +1,7 @@ /** - * functionvoid.cpp + * globals.cpp * @author Emiel Bruijntjes - * + * * An example file to show how global variables can be accessed */ @@ -18,48 +18,48 @@ using namespace std; /** * process_globals() - * + * * This function reads and modifies global variables */ Php::Value process_globals() { // all global variables can be accessed via the Php::GLOBALS variable, // which is more or less the same as the PHP $_GLOBALS variable - + // set a global variable Php::GLOBALS["a"] = 1; - + // increment a global variable Php::GLOBALS["b"] += 1; - + // set a global variable to be an array Php::GLOBALS["c"] = Php::Array(); - + // add a member to an array Php::GLOBALS["c"]["member"] = 123; - + // and increment it Php::GLOBALS["c"]["member"] += 77; - + // change value e Php::GLOBALS["e"] = Php::GLOBALS["e"][0]("hello"); - + // if a global variable holds a function, we can call it return Php::GLOBALS["d"](1,2,3); } // Symbols are exported according to the "C" language -extern "C" +extern "C" { // export the "get_module" function that will be called by the Zend engine - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // create extension static Php::Extension extension("globals","1.0"); - + // add function to extension - extension.add("process_globals"); - + extension.add("process_globals", + &Php::ZendCallable::invoke); // return the extension module return extension.module(); } diff --git a/Examples/ReturnObject/CMakeLists.txt b/Examples/ReturnObject/CMakeLists.txt new file mode 100644 index 00000000..7b95726b --- /dev/null +++ b/Examples/ReturnObject/CMakeLists.txt @@ -0,0 +1,5 @@ +set(SAMPLE_NAME "returnobject" ) +set(SAMPLE_SOURCES main.cpp master.h child.h) +set(SAMPLE_PHPFILE test.php) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/ReturnObject/main.cpp b/Examples/ReturnObject/main.cpp index 96fb4ec2..dc9070fe 100644 --- a/Examples/ReturnObject/main.cpp +++ b/Examples/ReturnObject/main.cpp @@ -1,3 +1,4 @@ +#include #include #include "master.h" #include "child.h" @@ -6,7 +7,7 @@ * tell the compiler that the get_module is a pure C function */ extern "C" { - + /** * Function that is called by PHP right after the PHP process * has started, and that returns an address of an internal PHP @@ -14,23 +15,23 @@ extern "C" { * * @return void* a pointer to an address that is understood by PHP */ - PHPCPP_EXPORT void *get_module() + MODULE_EXPORT void *get_module() { // static(!) Php::Extension object that should stay in memory // for the entire duration of the process (that's why it's static) static Php::Extension extension("returnobjecy", "1.0"); - - // we have to class - master and child + + // we have tWo class - master and child Php::Class master("master"); Php::Class child("child"); - + // the master class has one method - to return a child master.method<&Master::child>("child"); - + // add all classes to the extension extension.add(master); extension.add(child); - + // return the extension return extension; } diff --git a/Examples/simple/CMakeLists.txt b/Examples/simple/CMakeLists.txt new file mode 100644 index 00000000..30c3a7b6 --- /dev/null +++ b/Examples/simple/CMakeLists.txt @@ -0,0 +1,3 @@ +set(SAMPLE_NAME "simple" ) + +include(${PHPCPP_SOURCE_DIR}/cmake/sample.cmake) \ No newline at end of file diff --git a/Examples/simple/simple.cpp b/Examples/simple/simple.cpp index d9836ab6..72984db3 100644 --- a/Examples/simple/simple.cpp +++ b/Examples/simple/simple.cpp @@ -19,56 +19,56 @@ using namespace std; Php::Value bubblesort(Php::Parameters ¶ms) { cout << "start bubblesort" << endl; - + // the array that was passed Php::Value array(params[0]); - + cout << "go return" << endl; - + return array; - + // size of the array int size = array.size(); - + cout << "convert to native" << endl; - + int *x = new int[size]; for (int i=0; i("my_plus", { - Php::ByVal("a", Php::Type::Numeric), - Php::ByVal("b", Php::Type::Numeric), - Php::ByVal("c", "MyClass"), - Php::ByRef("d", Php::Type::String) - }); - - extension.add("bubblesort"); - + extension.add("my_plus", + &Php::ZendCallable::invoke, + { + Php::ByVal("a", Php::Type::Numeric), + Php::ByVal("b", Php::Type::Numeric), + Php::ByVal("c", "MyClass"), + Php::ByRef("d", Php::Type::String) + }); + + extension.add("bubblesort", + &Php::ZendCallable::invoke); + // define classes Php::Class myCustomClass("my_class"); myCustomClass.method<&MyCustomClass::myMethod>("mymethod"); myCustomClass.method<&MyCustomClass::__construct>("__construct"); - + // add to extension extension.add(myCustomClass); - + // return the module entry return extension.module(); } } - diff --git a/Modifications.md b/Modifications.md new file mode 100644 index 00000000..06ffe9fe --- /dev/null +++ b/Modifications.md @@ -0,0 +1,116 @@ + + +## Modify CMake definitions + - CMakeLists.txt + * Minimum version 3.11 + - Add cmake/sources.cmake, cmake/utils.cmake, cmake/sample.cmake + - Move zend/streambuf.cpp to phpcpp-common sources list, because of runtime error: undefined symbol: _ZN3Php9StreamBuf4syncEv + in static library build + +## Add file zend/modifiers.cpp + - Add definitions for the enums, because of link error in shared library build - undefined + + +## Modify include/visibility.h + - Add macro MODULE_EXPORT, for building extension + - Add macro USING_PHPCPP_DLL, for building extension with php-cpp built as shared lib(dll) + + +## Modify include/array.h + - Modify constructor + * Array(const std::initializer_list &value) + Note: + - Shared and Static library compiled, + - Link error occured when compiling sample - FunctionWithParameter + - link error LNK2019: unresolved external symbol "public: __cdecl Php::Value::Value(class std::initializer_list const &)" + + +## Modify include/call.h + - Remove PHPCPP_EXPORT from function declarations + - extern PHPCPP_EXPORT Value constant(const char *constant, size_t size); + - extern PHPCPP_EXPORT bool define(const char *name, size_t size, const Value &value); + - extern PHPCPP_EXPORT Value set_exception_handler(const std::function &handler); + - extern PHPCPP_EXPORT Value set_error_handler(const std::function &handler, Message message = Message::All); + - Note: + - compile error 'Php::constant': redefinition; different linkage + + +## Modify include/class.handler + - Remove PHPCPP_EXPORT from Class template + + +## Modify include/file.h and zend/file.cpp + - Move constructor definition to source file + - File(const char *name) + - File(const std::string &name) + - File(const Value &value) + - Note : + - Shared and Static library compiled, + - Link error occured when compiling sample - FunctionWithParameter + - error LNK2019: unresolved external symbol "const Php::File::`vftable'" + + +## Modify include/noexcept.h + - Add test for _MSC_VER >= 1400 , enable noexcept + + +## Modify include/streams.h + - Remove PHPCPP_EXPORT from function declarations + - Note : + - compile error data with thread storage duration may not have dll interface + + +## Modify zend/parametersimpl.h + - Modify contructor + - ParametersImpl(zval *this_ptr, uint32_t argc) + - old: zval arguments[argc]; + - new: zval* arguments = new zval[argc]; + - Note: compile error C2131: expression did not evaluate to a constant + + +## Modify include/value.h + - Move constructor definition to zend/value.cpp + - Construct to a specific type + - Constructor from an initializer list + - Note : + - Shared and Static library compiled, + - Link error occured when compiling sample - FunctionWithParameter + - error LNK2019: unresolved external symbol "const Php::Value::`vftable'" (??_7Value@Php@@6B@) referenced in function "public: __cdecl Php::Value::Value(enum Php::Type)" + + +## Modify include/module.h + - Add cast to HMODULE in virtual ~Persistent() + + +## Modify zend/callable.cpp + - Add cast in function definition + - void Callable::initialize(zend_function_entry *entry, const char *classname, int flags) const + - add cast: (zif_handler)_callback + - add cast: (zif_handler)&Callable::invoke + + +## Modify zend/classimpl.cpp + - Add cast in function definition + - zend_function *ClassImpl::getMethod(zend_object **object, zend_string *method, const zval *key) + - add cast: (zif_handler)&ClassImpl::callMethod + - zend_function *ClassImpl::getStaticMethod(zend_class_entry *entry, zend_string *method) + - add cast: (zif_handler)&ClassImpl::callMethod + - int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_function **func, zend_object **object_ptr) + - add cast: (zif_handler)&ClassImpl::callInvoke + +## Modify zend/value.cpp + - Modify function definition + - Value::exec(int argc, Value *argv) const definition: + - Value Value::exec(const char *name, int argc, Value *argv) const + - Value Value::exec(const char *name, int argc, Value *argv) const + - old: zval params[argc]; + - new: zval* params = new zval[argc]; + - Note : + - compile error C2131: expression did not evaluate to a constant + + - static Value do_exec(const zval *object, zval *method, int argc, zval *argv) definition: + - delete [] argv; + +## Sample Extension + - Replace PHPCPP_EXPORT with MODULE_EXPORt + - Linking with php-cpp built as dll, require defining USING_PHPCPP_DLL \ No newline at end of file diff --git a/README_PHP-CPP-Cmake.md b/README_PHP-CPP-Cmake.md new file mode 100644 index 00000000..198940d5 --- /dev/null +++ b/README_PHP-CPP-Cmake.md @@ -0,0 +1,81 @@ +PHP-CPP-cmake +============= +This is a fork of PHP-CPP, with goal to enable +building PHP-CPP with Cmake on Windows and Linux. + +Changes list: [Modifications.md](https://github.com/jefrisibarani/PHP-CPP-cmake/blob/master/Modifications.md) + +Sample PHP-CPP extension project: [PHP-CPP-SampleExtension](https://github.com/jefrisibarani/PHP-CPP-SampleExtension) + +Sample PHP-CPP extension project, using PHP-CPP-cmake as sub directory: [PHP-CPP-SampleExtension2](https://github.com/jefrisibarani/PHP-CPP-SampleExtension2) + +## Building with command line +Download project source, then from project source root dir, run cmake + +## Build on windows +Dowload php-dev from https://windows.php.net/download/, then extract to a folder for example: d:/dev/cpp_php/ts/php-7.4.30-devel-vc15-x64 +``` +cmake -S . -B build_shared ^ + -G "Visual Studio 15 2017" -T host=x64 -A x64 ^ + -DPHPCPP_BUILD_SHARED=TRUE ^ + -DPHP_DEV_DIR="d:/dev/cpp_php/ts/php-7.4.30-devel-vc15-x64" ^ + -DPHPCPP_COMPILE_TS=TRUE ^ + -DPHPCPP_ARCH="x86_64" +``` +``` +cmake --build build_shared --config=Release +``` +``` +cmake --build build_shared --config=Debug +``` +## Build on linux +We need php-dev package installed. + +Shared library - debug +``` +cmake -S . -B build_shared_d -G "Unix Makefiles" \ + -DPHPCPP_BUILD_SHARED=TRUE \ + -DCMAKE_BUILD_TYPE="Debug" +``` +``` +cmake --build build_shared_d +``` + +Shared library - release +``` +cmake -S . -B build_shared_r -G "Unix Makefiles" \ + -DPHPCPP_BUILD_SHARED=TRUE \ + -DCMAKE_BUILD_TYPE="Release" +``` +``` +cmake --build build_shared_r +``` + + + +## Successfully built on the following hosts: + +***Windows 11 (10.0.22000)*** +- Cmake version 3.22.2 +- Visual Studio 2017 (v14.16) +- MSVC 14.16.27023 +- Windows SDK Version 10.0.19041.0 +- PHP 7.4.30 (TS) with development package from https://windows.php.net/download/ + +***CentOS 7.9*** +- CMake 3.17.5 +- GCC 7.3.1 from devtoolset-7 +- GCC 11.2.1 from devtoolset-11 +- PHP 7.2.34 (NTS) + +***Windows 10 (10.0.19045)*** +- Cmake version 3.22.2 +- Visual Studio 2022 (v14.34) +- MSVC 19.34.31937.0 +- Windows SDK Version 10.0.22000.0 +- PHP 7.4.30 (TS) with development package from https://windows.php.net/download/ + +***Ubuntu Server 20.04.5*** +- CMake 3.25.2 +- GCC 9.4.0 +- PHP 7.4.33 (NTS) \ No newline at end of file diff --git a/build_all.cmd b/build_all.cmd new file mode 100644 index 00000000..86fde36a --- /dev/null +++ b/build_all.cmd @@ -0,0 +1,73 @@ +@echo off + +REM +REM Build extension with PHP-CPP static/shared, Release/Debug build +REM +REM Adapt the paths PHP_DEV_DIR, PHPCPP_COMPILE_TS and PHPCPP_ARCH +REM Run this script from project root dir +REM +REM To build with Visual Studio 2022, replace "Visual Studio 15 2017" +REM On line 24 and 54 with "Visual Studio 17 2022" +REM +REM Author: jefrisibarani@gmail.com +REM + + +SET PHP_DEV_DIR="d:/dev/cpp_php/ts/php-7.4.30-devel-vc15-x64" +SET PHPCPP_COMPILE_TS=TRUE +SET PHPCPP_ARCH="x86_64" + + +echo -------------------------------------------------------- +echo -- Configuring PHP-CPP shared library +echo -------------------------------------------------------- +cmake -S . -B build_shared ^ +-G "Visual Studio 15 2017" -T host=x64 -A x64 ^ +-DPHPCPP_BUILD_SHARED=TRUE ^ +-DPHP_DEV_DIR=%PHP_DEV_DIR% ^ +-DPHPCPP_COMPILE_TS=%PHPCPP_COMPILE_TS% ^ +-DPHPCPP_ARCH=%PHPCPP_ARCH% + + +timeout 3 > NUL +echo -------------------------------------------------------- +echo -- Building Shared Library - Release +echo -------------------------------------------------------- +cmake --build build_shared --config=Release + + +timeout 3 > NUL +echo -------------------------------------------------------- +echo -- Building Shared Library - Debug +echo -------------------------------------------------------- +cmake --build build_shared --config=Debug + + + + + + +echo -------------------------------------------------------- +echo -- Configuring PHP-CPP static library +echo -------------------------------------------------------- + +cmake -S . -B build_static ^ +-G "Visual Studio 15 2017" -T host=x64 -A x64 ^ +-DPHPCPP_BUILD_SHARED=FALSE ^ +-DPHP_DEV_DIR=%PHP_DEV_DIR% ^ +-DPHPCPP_COMPILE_TS=%PHPCPP_COMPILE_TS% ^ +-DPHPCPP_ARCH=%PHPCPP_ARCH% + + +timeout 3 > NUL +echo -------------------------------------------------------- +echo -- Building Static Library - Release +echo -------------------------------------------------------- +cmake --build build_static --config=Release + + +timeout 3 > NUL +echo -------------------------------------------------------- +echo -- Building Static Library - Debug +echo -------------------------------------------------------- +cmake --build build_static --config=Debug \ No newline at end of file diff --git a/build_all.sh b/build_all.sh new file mode 100644 index 00000000..2f0235ba --- /dev/null +++ b/build_all.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# +# Run this script from project root dir +# + +echo -------------------------------------------------------- +echo -- Building Shared Library - Debug +echo -------------------------------------------------------- +cmake -S . -B build_shared_d -G "Unix Makefiles" \ +-DPHPCPP_BUILD_SHARED=TRUE \ +-DCMAKE_BUILD_TYPE="Debug" + +sleep 5 +cmake --build build_shared_d +sleep 5 + + + +echo -------------------------------------------------------- +echo -- Building Shared Library - Release +echo -------------------------------------------------------- +cmake -S . -B build_shared_r -G "Unix Makefiles" \ +-DPHPCPP_BUILD_SHARED=TRUE \ +-DCMAKE_BUILD_TYPE="Release" + +sleep 5 +cmake --build build_shared_r +sleep 5 + + + +echo -------------------------------------------------------- +echo -- Building Static Library - Debug +echo -------------------------------------------------------- +cmake -S . -B build_static_d -G "Unix Makefiles" \ +-DPHPCPP_BUILD_SHARED=FALSE \ +-DCMAKE_BUILD_TYPE="Debug" + +sleep 5 +cmake --build build_static_d +sleep 5 + + + +echo -------------------------------------------------------- +echo -- Building Static Library - Release +echo -------------------------------------------------------- +cmake -S . -B build_static_r -G "Unix Makefiles" \ +-DPHPCPP_BUILD_SHARED=FALSE \ +-DCMAKE_BUILD_TYPE="Release" + +sleep 5 +cmake --build build_static_r +sleep 5 diff --git a/cmake/sample.cmake b/cmake/sample.cmake new file mode 100644 index 00000000..7e81c0c6 --- /dev/null +++ b/cmake/sample.cmake @@ -0,0 +1,50 @@ +if (NOT SAMPLE_NAME) + message(FATAL_ERROR "SAMPLE_NAME is not defined!") +endif () + +if(NOT SAMPLE_SOURCES) + set(SAMPLE_SOURCES ${SAMPLE_NAME}.cpp) +endif() + +if(NOT SAMPLE_PHPFILE) + set(SAMPLE_PHPFILE ${SAMPLE_NAME}.php) +endif() + +SET (SAMPLE_PHPFILE_DEST ${SAMPLE_NAME}.php) + +# ----------------------------------------------------------------------------- + + +add_library(${SAMPLE_NAME} MODULE ) +target_sources(${SAMPLE_NAME} PRIVATE ${SAMPLE_SOURCES} ) +target_include_directories(${SAMPLE_NAME} PRIVATE ${PHPCPP_INCLUDE_DIR}) +target_link_libraries(${SAMPLE_NAME} PRIVATE phpcpp) + +if(WIN32) + if (PHPCPP_BUILD_SHARED) + target_compile_definitions(${SAMPLE_NAME} PRIVATE USING_PHPCPP_DLL ) + endif() +else() + target_link_options(${SAMPLE_NAME} PRIVATE -shared ) + target_compile_options(${SAMPLE_NAME} PRIVATE -c -Wall ) +endif() + + + +# Copy binaries, resources to _output folder +# ----------------------------------------------------------------------------- +set(OUTPUT_EXTDIR "${PHPCPP_OUTPUT_DIR}/ext_static") +if (PHPCPP_BUILD_SHARED) + set(OUTPUT_EXTDIR "${PHPCPP_OUTPUT_DIR}/ext_shared") +endif() + +# Copy extension to _output dir +add_custom_command(TARGET ${SAMPLE_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT_EXTDIR}/$<$:debug>$<$:release> + COMMAND ${CMAKE_COMMAND} -E copy $ ${OUTPUT_EXTDIR}/$<$:debug>$<$:release> ) + +# Copy php sample to _output dir +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${SAMPLE_PHPFILE}) + add_custom_command(TARGET ${SAMPLE_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${SAMPLE_PHPFILE} ${OUTPUT_EXTDIR}/$<$:debug>$<$:release>/${SAMPLE_PHPFILE_DEST} ) +endif() \ No newline at end of file diff --git a/cmake/sources.cmake b/cmake/sources.cmake new file mode 100644 index 00000000..f4fdeadf --- /dev/null +++ b/cmake/sources.cmake @@ -0,0 +1,145 @@ +file(GLOB PHPCPP_COMMON_SOURCES CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/common/modifiers.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/common/streambuf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/streambuf.cpp + ) + +file(GLOB PHPCPP_COMMON_HEADERS CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/common/extensionbase.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/includes.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/streambuf.h + ) + +file(GLOB PHPCPP_ZEND_SOURCES CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/zend/base.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/callable.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/classbase.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/classimpl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/constant.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/constantfuncs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/error.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/eval.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/exception.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/exception_handler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/exists.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/extension.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/extensionimpl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/file.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/function.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/functor.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/global.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/globals.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/hashmember.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/ini.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/inivalue.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/iteratorimpl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/members.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/modifiers.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/module.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/namespace.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/object.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/sapi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/script.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/stream.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/streams.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/super.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/throwable.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/value.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/valueiterator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/zendcallable.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/zend/zval.cpp + ) + + +file(GLOB PHPCPP_ZEND_HEADERS CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/zend/arithmetic.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/boolmember.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/callable.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/classimpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/classtype.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/compileroptions.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/constantimpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/delayedfree.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/executestate.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/extensionimpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/extensionpath.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/floatmember.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/functor.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/hashiterator.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/includes.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/init.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/invaliditerator.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/iteratorimpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/lowercase.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/member.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/method.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/module.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/nativefunction.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/notimplemented.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/nullmember.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/numericmember.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/objectimpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/opcodes.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/parametersimpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/property.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/rethrowable.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/state.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/string.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/stringmember.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/symbol.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/traverseiterator.h + ${CMAKE_CURRENT_SOURCE_DIR}/zend/valueiteratorimpl.h + ) + +file(GLOB PHPCPP_HEADERS_FILES CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/include/argument.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/array.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/arrayaccess.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/byref.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/byval.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/call.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/class.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/classbase.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/classtype.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/constant.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/countable.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/deprecated.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/error.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/exception.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/extension.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/file.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/function.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/global.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/globals.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/hashmember.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/hashparent.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/ini.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/inivalue.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/interface.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/iterator.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/message.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/modifiers.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/namespace.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/noexcept.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/object.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/parameters.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/platform.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/script.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/serializable.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/stream.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/streams.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/super.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/thread_local.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/throwable.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/traversable.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/type.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/value.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/valueiterator.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/version.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/visibility.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/zendcallable.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/zval.h + ${CMAKE_CURRENT_SOURCE_DIR}/phpcpp.h + ) diff --git a/cmake/utils.cmake b/cmake/utils.cmake new file mode 100644 index 00000000..3f53da22 --- /dev/null +++ b/cmake/utils.cmake @@ -0,0 +1,94 @@ +function(find_php_dev phpcfg) + + set(PHP_CONFIG_CMD ${phpcfg}) + + find_program(PHP_CONFIG NAMES ${PHP_CONFIG_CMD}) + + if (PHP_CONFIG) + # get include dirs + execute_process(COMMAND ${PHP_CONFIG_CMD} --includes + OUTPUT_VARIABLE php_CONFIG_INCS + RESULT_VARIABLE RET + ERROR_QUIET ) + + if(RET EQUAL 0) + string(STRIP "${php_CONFIG_INCS}" php_CONFIG_INCS) + separate_arguments(php_CONFIG_INCS_LIST NATIVE_COMMAND "${php_CONFIG_INCS}") + # parse include dirs, drop -I prefixes + set(php_INCLUDE_DIRS) + foreach(arg IN LISTS php_CONFIG_INCS_LIST) + if("${arg}" MATCHES "^-I(.*)$") + list(APPEND php_INCLUDE_DIRS "${CMAKE_MATCH_1}") + endif() + endforeach() + endif() + + # get libs + execute_process(COMMAND ${PHP_CONFIG_CMD} --libs + OUTPUT_VARIABLE php_CONFIG_LIBS + RESULT_VARIABLE RET + ERROR_QUIET ) + + if(RET EQUAL 0) + string(STRIP "${php_CONFIG_LIBS}" php_CONFIG_LIBS) + separate_arguments(php_CONFIG_LIBS_LIST NATIVE_COMMAND "${php_CONFIG_LIBS}") + # parse libraries, drop -l prefixes + set(php_DEPENDS_LIBS) + foreach(arg IN LISTS php_CONFIG_LIBS_LIST) + if("${arg}" MATCHES "^-l(.*)$") + list(APPEND php_DEPENDS_LIBS "${CMAKE_MATCH_1}") + endif() + endforeach() + endif() + + # get ldflags + execute_process(COMMAND ${PHP_CONFIG_CMD} --ldflags + OUTPUT_VARIABLE php_CONFIG_LDFLAGS + RESULT_VARIABLE RET + ERROR_QUIET ) + + if(RET EQUAL 0) + string(STRIP "${php_CONFIG_LDFLAGS}" php_LDFLAGS) + endif() + + # get version number + execute_process(COMMAND ${PHP_CONFIG} --vernum + OUTPUT_VARIABLE php_CONFIG_VERNUM + RESULT_VARIABLE RET + ERROR_QUIET ) + + if(RET EQUAL 0) + string(STRIP "${php_CONFIG_VERNUM}" php_VERNUMBER) + endif() + + + # get version string + execute_process(COMMAND ${PHP_CONFIG} --version + OUTPUT_VARIABLE php_CONFIG_VERSTRING + RESULT_VARIABLE RET + ERROR_QUIET ) + + if(RET EQUAL 0) + string(STRIP "${php_CONFIG_VERSTRING}" php_VERSTRING) + endif() + + + set(PHP_DEV_FOUND TRUE PARENT_SCOPE) + set(PHP_INCLUDE_DIRS ${php_INCLUDE_DIRS} PARENT_SCOPE) + set(PHP_DEPENDS_LIBS ${php_DEPENDS_LIBS} PARENT_SCOPE) + set(PHP_LDFLAGS ${php_LDFLAGS} PARENT_SCOPE) + set(PHP_VERSION_NUMBER ${php_VERNUMBER} PARENT_SCOPE) + set(PHP_VERSION ${php_VERSTRING} PARENT_SCOPE) + + else() + + set(PHP_DEV_FOUND FALSE PARENT_SCOPE) + set(PHP_INCLUDE_DIRS "" PARENT_SCOPE) + set(PHP_DEPENDS_LIBS "" PARENT_SCOPE) + set(PHP_LDFLAGS "" PARENT_SCOPE) + set(PHP_VERSION_NUMBER "" PARENT_SCOPE) + set(PHP_VERSION "" PARENT_SCOPE) + + endif(PHP_CONFIG) + +endfunction() \ No newline at end of file diff --git a/include/array.h b/include/array.h index 8321bc6f..a165bce3 100644 --- a/include/array.h +++ b/include/array.h @@ -65,7 +65,8 @@ class PHPCPP_EXPORT Array : public Value * Constructor from an initializer list * @param value */ - Array(const std::initializer_list &value) : Value(value) {} + template + Array(const std::initializer_list &value) : Value(value) {} // end of visual c++ check # endif diff --git a/include/call.h b/include/call.h index 6e0229fd..67e44a05 100644 --- a/include/call.h +++ b/include/call.h @@ -19,9 +19,9 @@ extern PHPCPP_EXPORT bool class_exists(const char *classname, size_t size, b static inline bool class_exists(const char *classname, bool autoload = true) { return class_exists(classname, strlen(classname), autoload); } static inline bool class_exists(const std::string &classname, bool autoload = true) { return class_exists(classname.c_str(), classname.size(), autoload); } extern PHPCPP_EXPORT Value constant(const char *constant); -extern PHPCPP_EXPORT Value constant(const char *constant, size_t size); +extern /*PHPCPP_EXPORT*/Value constant(const char *constant, size_t size); extern PHPCPP_EXPORT Value constant(const std::string &constant); -extern PHPCPP_EXPORT bool define(const char *name, size_t size, const Value &value); +extern /*PHPCPP_EXPORT*/bool define(const char *name, size_t size, const Value &value); extern PHPCPP_EXPORT bool define(const char *name, const Value &value); extern PHPCPP_EXPORT bool define(const std::string &name, const Value &value); extern PHPCPP_EXPORT bool defined(const char *constant); @@ -46,8 +46,8 @@ extern PHPCPP_EXPORT Value require(const char *filename); static inline Value require(const std::string &filename) { return require(filename.c_str()); } extern PHPCPP_EXPORT Value require_once(const char *filename); static inline Value require_once(const std::string &filename) { return require_once(filename.c_str()); } -extern PHPCPP_EXPORT Value set_exception_handler(const std::function &handler); -extern PHPCPP_EXPORT Value set_error_handler(const std::function &handler, Message message = Message::All); +extern /*PHPCPP_EXPORT*/Value set_exception_handler(const std::function &handler); +extern /*PHPCPP_EXPORT*/Value set_error_handler(const std::function &handler, Message message = Message::All); extern PHPCPP_EXPORT Value error_reporting(Message message); extern PHPCPP_EXPORT const char *sapi_name(); @@ -133,4 +133,3 @@ static inline Value isset(const HashMember &member) { return member.exist * End of namespace */ } - diff --git a/include/class.h b/include/class.h index e18220ad..2b4e7682 100644 --- a/include/class.h +++ b/include/class.h @@ -24,7 +24,7 @@ namespace Php { * Class definition of the class */ template -class PHPCPP_EXPORT Class : private ClassBase +class /*PHPCPP_EXPORT*/ Class : private ClassBase { public: /** diff --git a/include/file.h b/include/file.h index 4fab1c59..b92a4729 100644 --- a/include/file.h +++ b/include/file.h @@ -40,19 +40,19 @@ class PHPCPP_EXPORT File * * @param name the filename */ - File(const char *name) : File(name, ::strlen(name)) {} + File(const char *name); /** * Alternative constructor with a string object * @param name the filename */ - File(const std::string &name) : File(name.c_str(), name.size()) {} + File(const std::string &name); /** * Alternative constructor with a Value object * @param name the filename */ - File(const Value &value) : File(value.stringValue()) {} + File(const Value &value); /** * Destructor diff --git a/include/noexcept.h b/include/noexcept.h index 25dc1a44..b51831d8 100644 --- a/include/noexcept.h +++ b/include/noexcept.h @@ -11,11 +11,15 @@ /** * Macro to be able to support MSVC compiler */ + #ifndef _NOEXCEPT # ifndef _MSC_VER # define _NOEXCEPT noexcept # else -# define _NOEXCEPT __declspec(nothrow) +# if _MSC_VER >= 1400 +# define _NOEXCEPT noexcept +# else +# define _NOEXCEPT __declspec(nothrow) +# endif # endif #endif - diff --git a/include/streams.h b/include/streams.h index b5e45003..f721c8b0 100644 --- a/include/streams.h +++ b/include/streams.h @@ -21,14 +21,14 @@ namespace Php { /** * Define the out and err objects */ -extern thread_local PHPCPP_EXPORT std::ostream out; -extern thread_local PHPCPP_EXPORT std::ostream error; -extern thread_local PHPCPP_EXPORT std::ostream notice; -extern thread_local PHPCPP_EXPORT std::ostream warning; -extern thread_local PHPCPP_EXPORT std::ostream deprecated; +// NOTE: PHPCPP_EXPORT causes MSVC Compiler Error C2492 in Shared build +extern thread_local /*PHPCPP_EXPORT*/ std::ostream out; +extern thread_local /*PHPCPP_EXPORT*/ std::ostream error; +extern thread_local /*PHPCPP_EXPORT*/ std::ostream notice; +extern thread_local /*PHPCPP_EXPORT*/ std::ostream warning; +extern thread_local /*PHPCPP_EXPORT*/ std::ostream deprecated; /** * End namespace */ } - diff --git a/include/throwable.h b/include/throwable.h index 8b9adafa..2c32462a 100644 --- a/include/throwable.h +++ b/include/throwable.h @@ -9,7 +9,7 @@ * @author Emiel Bruijntjes * @copyright 2013 - 2019 Copernica BV */ -#include +#include #include /** diff --git a/include/value.h b/include/value.h index 45f7464e..dc3ad4b4 100644 --- a/include/value.h +++ b/include/value.h @@ -66,7 +66,7 @@ class PHPCPP_EXPORT Value : private HashParent * Construct to a specific type * @param value */ - Value(Type type) : Value() { setType(type); } + Value(Type type); /** * Constructors from a vector (this will create an array) @@ -90,14 +90,7 @@ class PHPCPP_EXPORT Value : private HashParent * @param value */ template - Value(const std::initializer_list &value) : Value(Type::Array) - { - // index - int i = 0; - - // set all elements - for (auto &elem : value) setRaw(i++, elem); - } + Value(const std::initializer_list &value); // end of visual c++ check # endif @@ -614,7 +607,7 @@ class PHPCPP_EXPORT Value : private HashParent */ virtual bool contains(const std::string &key) const override { - return contains(key.c_str(), key.size()); + return contains(key.c_str(), static_cast(key.size())); } /** diff --git a/include/visibility.h b/include/visibility.h index afb8a6b5..3228cb4f 100644 --- a/include/visibility.h +++ b/include/visibility.h @@ -16,15 +16,35 @@ #ifdef __GNUC__ #define PHPCPP_EXPORT __attribute__ ((dllexport)) #else + // building PHP-CPP as dll, BUILDING_PHPCPP defined in PHP-CPP project #define PHPCPP_EXPORT __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. #endif #else #ifdef __GNUC__ #define DLL_EXPORT __attribute__ ((dllimport)) + #define PHPCPP_EXPORT __attribute__ ((dllimport)) #else - #define DLL_EXPORT __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. + #define DLL_EXPORT __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. + + #ifdef USING_PHPCPP_DLL + // PHP-CPP was built as dll, USING_PHPCPP_DLL defined in extension project + // extension uses phpcpp as shared(dll) library + #define PHPCPP_EXPORT __declspec(dllimport) + #else + // PHP-CPP was built as static library, extension uses phpcpp as static library + #define PHPCPP_EXPORT + #endif #endif #endif + + // MODULE_EXPORT defined in extension source + #ifdef __GNUC__ + #define MODULE_EXPORT __attribute__ ((dllexport)) + #else + #define MODULE_EXPORT __declspec(dllexport) + #endif + #else + #define MODULE_EXPORT __attribute__ ((visibility ("default"))) #define PHPCPP_EXPORT __attribute__ ((visibility ("default"))) #endif diff --git a/test_extension.cmd b/test_extension.cmd new file mode 100644 index 00000000..a1203fda --- /dev/null +++ b/test_extension.cmd @@ -0,0 +1,56 @@ +@echo off + +REM +REM Test the extension +REM +REM Author: jefrisibarani@gmail.com +REM + +set argC=0 +for %%x in (%*) do Set /A argC+=1 + +if %argC% NEQ 3 ( + echo usage : test_extension sample_name build_mode lib_mode + echo sample_name : sample name, same with php script file name and extension name + echo build_mode : debug or release + echo lib_mode : shared or static + echo example : test_extension functionwithparameters release shared + echo : test_extension functionwithparameters release static + exit /b +) + +set arg_sample=%1 +set arg_build=%2 +set arg_lib=%3 + +set drive=%~d0% +set workdir=%~p0% +set prj_root=%drive%%workdir% +set php_root=d:\wampje\php\php.7.4.30 +set phpcpp_compiled_root=%prj_root%\_output + +rem sample name +set sample=%arg_sample% + +rem debug or release +set build_mode=debug +if "%arg_build%"=="release" ( + set build_mode=release +) + +rem static or shared +set lib_mode=shared +if "%arg_lib%"=="static" ( + set lib_mode=static +) + + +if "%lib_mode%"=="shared" ( + copy %phpcpp_compiled_root%\lib_shared\%build_mode%\phpcpp.dll %php_root% /y +) + +%php_root%\php.exe -dextension=%prj_root%_output\ext_%lib_mode%\%build_mode%\%sample%.dll %prj_root%_output\ext_%lib_mode%\%build_mode%\%sample%.php + +if "%lib_mode%"=="shared" ( + del %php_root%\phpcpp.dll +) \ No newline at end of file diff --git a/zend/callable.cpp b/zend/callable.cpp index 98c98140..5360f55d 100644 --- a/zend/callable.cpp +++ b/zend/callable.cpp @@ -90,7 +90,7 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int { // that's nice, we simply install the callback // no need to store any data in a lookup map - entry->handler = _callback; + entry->handler = (zif_handler)_callback; } else { @@ -107,7 +107,7 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int // we use our own invoke method, which does a lookup // in the map we just installed ourselves in - entry->handler = &Callable::invoke; + entry->handler = (zif_handler)&Callable::invoke; } // fill the members of the entity, and hide a pointer to the current object in the name diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp index c78ab216..650163ad 100644 --- a/zend/classimpl.cpp +++ b/zend/classimpl.cpp @@ -223,7 +223,7 @@ zend_function *ClassImpl::getMethod(zend_object **object, zend_string *method, c function->num_args = 0; function->required_num_args = 0; function->arg_info = nullptr; - function->handler = &ClassImpl::callMethod; + function->handler = (zif_handler)&ClassImpl::callMethod; // store pointer to ourselves data->self = self(entry); @@ -267,7 +267,7 @@ zend_function *ClassImpl::getStaticMethod(zend_class_entry *entry, zend_string * function->num_args = 0; function->required_num_args = 0; function->arg_info = nullptr; - function->handler = &ClassImpl::callMethod; + function->handler = (zif_handler)&ClassImpl::callMethod; // store pointer to ourselves data->self = self(entry); @@ -311,7 +311,7 @@ int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_funct function->num_args = 0; function->required_num_args = 0; function->arg_info = nullptr; - function->handler = &ClassImpl::callInvoke; + function->handler = (zif_handler)&ClassImpl::callInvoke; // store pointer to ourselves (note that the entry_ptr is useless // inside this function as it is always uninitialized for some reason) diff --git a/zend/file.cpp b/zend/file.cpp index fa0d0127..ab0dfe03 100644 --- a/zend/file.cpp +++ b/zend/file.cpp @@ -32,6 +32,31 @@ File::File(const char *name, size_t size) _path = zend_resolve_path(name, size); } +/* +Constructor implemented in .cpp file , not in .h because +MSVC Shared build error LNK2019: unresolved external symbol "const Php::File::`vftable'" (??_7File@Php@@6B@) +referenced in function "public: __cdecl Php::File::File(class std::basic_string,class std::allocator > const &)" (??0File@Php@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) +*/ + +/** + * Alternative constructor with just a filename + * + * @param name the filename + */ +File::File(const char *name) : File(name, ::strlen(name)) {} + +/** + * Alternative constructor with a string object + * @param name the filename + */ +File::File(const std::string &name) : File(name.c_str(), name.size()) {} + +/** + * Alternative constructor with a Value object + * @param name the filename + */ +File::File(const Value &value) : File(value.stringValue()) {} + /** * Destructor */ @@ -141,4 +166,3 @@ Value File::once() * End of namespace */ } - diff --git a/zend/modifiers.cpp b/zend/modifiers.cpp new file mode 100644 index 00000000..7f70809a --- /dev/null +++ b/zend/modifiers.cpp @@ -0,0 +1,41 @@ +/** + * Modifiers.cpp + * + * Modifiers implementation file + * + * @author Emiel Bruijntjes + * @copyright 2015 Copernica BV + */ + +/** + * Dependencies + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace Php { + +/** + * The modifiers are constants + */ +#if defined(_MSC_VER) && defined(BUILDING_PHPCPP) + PHPCPP_EXPORT const int Static = 0; + PHPCPP_EXPORT const int Abstract = 0; + PHPCPP_EXPORT const int Final = 0; + PHPCPP_EXPORT const int Public = 0; + PHPCPP_EXPORT const int Protected = 0; + PHPCPP_EXPORT const int Private = 0; + PHPCPP_EXPORT const int Const = 0; + + /** + * Modifiers that are supported for methods and properties + */ + PHPCPP_EXPORT const int MethodModifiers = 0; + PHPCPP_EXPORT const int PropertyModifiers = 0; +#endif // defined(__VISUALC__) +/** + * End of namespace + */ +} diff --git a/zend/module.h b/zend/module.h index 7902f8e9..9a23c8a4 100644 --- a/zend/module.h +++ b/zend/module.h @@ -8,15 +8,15 @@ * from an ~user directory to be able to make changes to the globalle running * apache process, and for example make changes to catch data from other websites * running on the same host. - * - * However, people who are in a position to write C++ and deploy code however, + * + * However, people who are in a position to write C++ and deploy code however, * already _ARE_ in a position to do dangerous things. For them we do not want * these safety checks. In fact, we want to offer raw access, so that they can * open modules - no matter what. So we had to make our own copy of the dl() * function, and because we're here in C++ context, we do it a little nicer * than the original C++ code. This module class is a utility class used by * our own dl() implementation. - * + * * @author Emiel Bruijntjes * @copyright 2015 Copernica BV */ @@ -25,7 +25,7 @@ * Set up namespace */ namespace Php { - + /** * Class definition */ @@ -37,13 +37,13 @@ class Module * @var void* */ void *_handle; - + /** * The module entry * @var zend_module_entry */ zend_module_entry *_entry = nullptr; - + /** * Internal helper class with persistent modules @@ -56,32 +56,36 @@ class Module * @var std::set */ std::set _handles; - + public: /** * Constructor */ Persistent() {} - + /** * Destructor */ - virtual ~Persistent() + virtual ~Persistent() { // remove all handles while (!_handles.empty()) { // get first handle auto iter = _handles.begin(); - + // remove the handle +#ifdef _MSC_VER + DL_UNLOAD((HMODULE)*iter); +#else DL_UNLOAD(*iter); - +#endif + // remove from set _handles.erase(iter); } } - + /** * Check whether a handle is already persistently opened * @param handle @@ -91,7 +95,7 @@ class Module { return _handles.find(handle) != _handles.end(); } - + /** * Add a library persistently * @param module @@ -112,11 +116,11 @@ class Module public: /** * Constructor - * + * * A module can be loaded persistently. This means that the variables in * the module will keep in scope for as long as Apache runs, even though * the extension is not active in other page views - * + * * @param module Name of the module * @param persistent Should it be loaded persistently */ @@ -124,27 +128,27 @@ class Module { // the path we're going to load ExtensionPath path(module); - + // load the module _handle = DL_LOAD(path); - + // handle should be valid if (!_handle) return; - + // if we have to open it persistently, we open it for a second time so that // the refcounter always stays 1 or higher if (persistent && !_persistent.contains(_handle)) _persistent.add(module); - + // we have to call the get_module() function Symbol get_module(_handle, "get_module"); - + // was the get_module() function found if (!get_module) return; // retrieve the module entry _entry = get_module(); } - + /** * Destructor */ @@ -153,7 +157,7 @@ class Module // if the handle is still valid, we have to unload it if (_handle) DL_UNLOAD((DL_HANDLE)_handle); } - + /** * Check if the module is valid * @return bool @@ -162,14 +166,14 @@ class Module { // module-entry must exist if (!_handle || !_entry) return false; - + // check api compatibility if (_entry->zend_api != ZEND_MODULE_API_NO) return false; - + // and other stuff return strcmp(_entry->build_id, ZEND_MODULE_BUILD_ID) == 0; } - + /** * Start the module * @return bool @@ -178,22 +182,22 @@ class Module { // this is not possible if the module is invalid in the first place if (!valid()) return false; - + // the Zend engine sets a number of properties in the entry class, we do that here too // note that it would be better to call zend_next_free_module() to find the next module // number, but some users complain that this function is not always available _entry->type = MODULE_TEMPORARY; _entry->module_number = zend_hash_num_elements(&module_registry) + 1; _entry->handle = _handle; - + // @todo does loading an extension even work in a multi-threading setup? - + // register the module, this apparently returns a copied entry pointer auto *entry = zend_register_module_ex(_entry); // forget the entry, so that a new call to start() will fail too _entry = nullptr; - + // leap out on failure if (entry == NULL) return false; @@ -206,20 +210,19 @@ class Module // call the startup function if (entry->request_startup_func(MODULE_TEMPORARY, entry->module_number) == FAILURE) return false; } - + // all is ok, we can forget about the handle now, so that is won't get destructed _handle = nullptr; // enable full-table-cleanup, because inside the Zend-engine this is done too EG(full_tables_cleanup) = 1; - + // we're ready return true; } }; - + /** * End of namespace */ } - diff --git a/zend/parametersimpl.h b/zend/parametersimpl.h index fa58d9fa..58f308f2 100644 --- a/zend/parametersimpl.h +++ b/zend/parametersimpl.h @@ -29,7 +29,7 @@ class ParametersImpl : public Parameters reserve(argc); // array to store all the arguments in - zval arguments[argc]; + zval* arguments = new zval[argc]; // retrieve the arguments zend_get_parameters_array_ex(argc, arguments); @@ -40,6 +40,8 @@ class ParametersImpl : public Parameters // append value emplace_back(&arguments[i]); } + + delete [] arguments; } /** @@ -60,4 +62,3 @@ class ParametersImpl : public Parameters * End of namespace */ } - diff --git a/zend/value.cpp b/zend/value.cpp index 6ded9556..2ebbf5a3 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -197,6 +197,32 @@ Value::Value(const Base *object) */ Value::Value(const IniValue &value) : Value((const char *)value) {} +/** + * Construct to a specific type + * @param value + */ +Value::Value(Type type) : Value() { setType(type); } + +// old visual c++ environments have no support for initializer lists +#if !defined(_MSC_VER) || _MSC_VER >= 1800 + +/** + * Constructor from an initializer list + * @param value + */ +template +Value::Value(const std::initializer_list &value) : Value(Type::Array) +{ + // index + int i = 0; + + // set all elements + for (auto &elem : value) setRaw(i++, elem); +} + +// end of visual c++ check +#endif + /** * Copy constructor * @param value @@ -763,12 +789,15 @@ static Value do_exec(const zval *object, zval *method, int argc, zval *argv) // remember current state of the PHP engine State state; - + // call the function // we're casting the const away here, object is only const so we can call this method // from const methods after all.. if (call_user_function_ex(CG(function_table), (zval*) object, method, &retval, argc, argv, 1, nullptr) != SUCCESS) { + if (argv != nullptr) + delete[] argv; + // throw an exception, the function does not exist throw Error("Invalid call to "+Value(method).stringValue()); @@ -777,6 +806,9 @@ static Value do_exec(const zval *object, zval *method, int argc, zval *argv) } else { + if (argv != nullptr) + delete[] argv; + // the state object checks if a new exception is added to the stack, which means // that an exception or error occured during the call to php space state.rethrow(); @@ -892,7 +924,7 @@ Value Value::call(const char *name) Value Value::exec(int argc, Value *argv) const { // array of zvals to execute - zval params[argc]; + zval* params = new zval[argc]; // convert all the values for(int i = 0; i < argc; i++) { params[i] = *argv[i]._val; } @@ -914,7 +946,7 @@ Value Value::exec(const char *name, int argc, Value *argv) const Value method(name); // array of zvals to execute - zval params[argc]; + zval* params = new zval[argc]; // convert all the values for(int i = 0; i < argc; i++) { params[i] = *argv[i]._val; } @@ -936,7 +968,7 @@ Value Value::exec(const char *name, int argc, Value *argv) Value method(name); // array of zvals to execute - zval params[argc]; + zval* params = new zval[argc]; // convert all the values for(int i = 0; i < argc; i++) { params[i] = *argv[i]._val; } @@ -1845,4 +1877,3 @@ std::ostream &operator<<(std::ostream &stream, const Value &value) * End of namespace */ } -