-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


[ ] PHP 7 C++

, 12 2017 . 10:29 +
, C++ PHP. , 5 7.

PHP, , , 2014 , 5. php.net , , wiki, 5 . , , .
, PHP, .

, API PHP , , Wrapping C++ Classes in a PHP Extension PHP 7.

Linux, Kubuntu. config , PHP , .


php-dev, gcc, php. , , .


OpenCV, >=2.3.1

ext_skel. . , .

/ext PHP
ext_skel :

./ext_skel --extname=phpcv

phpcv - . tests config.m4, php_phpcv.h phpcv.c. phpcv.c phpcv.cpp.

config.m4


, phpize .

bash . acinclude.m4 aclocal.m4 php, . , dnl , .

, .

config.m4

PHP_ARG_ENABLE(phpcv, whether to enable phpcv support,
    [  --enable-phpcv           Enable phpcv support])

if test "$PHP_PHPCV" != "no"; then
    PHP_REQUIRE_CXX()

    SEARCH_PATH="/usr/local /usr /opt/local"
    SEARCH_FOR="/include/opencv2/opencv.hpp"

    if test -r $PHP_PHPCV/$SEARCH_FOR; then
        CV_DIR=$PHP_PHPCV
    else
        AC_MSG_CHECKING([for opencv in default path])
        for i in $SEARCH_PATH ; do
            if test -r $i/$SEARCH_FOR; then
                CV_DIR=$i
                AC_MSG_RESULT(found in $i)
                break
            fi
        done
    fi

    if test -z "$CV_DIR"; then
        AC_MSG_RESULT([not found])
        AC_MSG_ERROR([Please reinstall the OpenCV distribution])
    fi

    AC_CHECK_HEADER([$CV_DIR/include/opencv2/objdetect/objdetect.hpp], [], AC_MSG_ERROR('opencv2/objdetect/objdetect.hpp' header not found))
    AC_CHECK_HEADER([$CV_DIR/include/opencv2/highgui/highgui.hpp], [], AC_MSG_ERROR('opencv2/highgui/highgui.hpp' header not found))

    PHP_ADD_LIBRARY_WITH_PATH(opencv_objdetect, $CV_DIR/lib, PHPCV_SHARED_LIBADD)
    PHP_ADD_LIBRARY_WITH_PATH(opencv_highgui, $CV_DIR/lib, PHPCV_SHARED_LIBADD)
    PHP_ADD_LIBRARY_WITH_PATH(opencv_imgproc, $CV_DIR/lib, PHPCV_SHARED_LIBADD)

    PHP_SUBST(PHPCV_SHARED_LIBADD)
    PHP_NEW_EXTENSION(phpcv, phpcv.cpp, $ext_shared,, -std=c++0x -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi



PHP_ARG_ENABLE , PHP .
PHP_REQUIRE_CXX() , C++
, bash opencv.
AC_CHECK_HEADER
PHP_ADD_LIBRARY_WITH_PATH shared
PHP_SUBST make
PHP_NEW_EXTENSION , *.cpp , , .

php_phpcv.h


php_phpcv.h
#ifndef PHP_PHPCV_H
#define PHP_PHPCV_H

#define PHP_PHPCV_EXTNAME "phpcv"
#define PHP_PHPCV_VERSION "0.2.0"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

extern "C" {
#include "php.h"
#include "ext/standard/info.h"
}

#ifdef ZTS
#include "TSRM.h"
#endif

extern zend_module_entry phpcv_module_entry;
#define phpext_phpcv_ptr &phpcv_module_entry

#if defined(ZTS) && defined(COMPILE_DL_PHPCV)
ZEND_TSRMLS_CACHE_EXTERN();
#endif

#endif	/* PHP_PHPCV_H */





extern "C" { ... }
C++ C PHP.

phpcv.cpp


, -, C++ .
cv::CascadeClassifier::detectMultiScale().

, :

/**
 * @see cv::CascadeClassifier::detectMultiScale()
 * @param string $imgPath
 * @param string $cascadePath
 * @param double $scaleFactor
 * @param int $minNeighbors
 *
 * @return array
 */
function cv_detect_multiscale($imgPath, $cascadePath, $scaleFactor, $minNeighbors) {
}

phpcv.cpp
#include "php_phpcv.h"
#include objdetect/objdetect.hpp>
#include highgui/highgui.hpp>
#include imgproc/imgproc.hpp>

PHP_MINFO_FUNCTION(phpcv) {
    php_info_print_table_start();
    php_info_print_table_header(2, "phpcv support", "enabled");
    php_info_print_table_end();
}

PHP_FUNCTION(cv_detect_multiscale) {
    char *imgPath = NULL, *cascadePath = NULL;
    long imgPathLen, cascadePathLen, minNeighbors;
    double scaleFactor, minWidth, minHeight;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssdl", &imgPath, &imgPathLen, &cascadePath, &cascadePathLen, &scaleFactor, &minNeighbors) == FAILURE) {
        RETURN_FALSE;
    }

    // Read Image
    cv::Mat image;
    image = cv::imread(imgPath, CV_LOAD_IMAGE_GRAYSCALE);
    if (image.empty()) {
        RETURN_FALSE;
    }
    equalizeHist(image, image);

    //min size for detected object, discarding objects smaller than this
    minWidth = image.size().width / 10;
    minHeight = image.size().height / 10;

    // Load Face cascade (.xml file)
    cv::CascadeClassifier faceCascade;
    if (!faceCascade.load(cascadePath)) {
        RETURN_FALSE;
    }

    // Detect faces
    std::vector faces;
    faceCascade.detectMultiScale(image, faces, scaleFactor, minNeighbors, 0, cv::Size(minWidth, minHeight));

    array_init(return_value);

    // Build array to return
    for ( int i = 0; i < faces.size(); i++ ) {
        // Now we have: faces[i].x faces[i].y faces[i].width faces[i].height
        zval face;
        array_init(&face);
        add_assoc_long(&face, "x", faces[i].x);
        add_assoc_long(&face, "y", faces[i].y);
        add_assoc_long(&face, "w", faces[i].width);
        add_assoc_long(&face, "h", faces[i].height);

        add_next_index_zval(return_value, &face);
    }
}

const zend_function_entry phpcv_functions[] = {
    PHP_FE(cv_detect_multiscale, NULL)
    PHP_FE_END
};

zend_module_entry phpcv_module_entry = {
    STANDARD_MODULE_HEADER,
    PHP_PHPCV_EXTNAME,
    phpcv_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    PHP_MINFO(phpcv),
    PHP_PHPCV_VERSION,
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_PHPCV
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE();
#endif
ZEND_GET_MODULE(phpcv)
#endif



PHP_MINFO_FUNCTION phpinfo()
PHP_FUNCTION(cv_detect_multiscale) . zend_parse_parameters ++. opencv .
zend_function_entry , .
zend_module_entry , , . NULL , shutdown , .

. , .

tests


, - . *.phpt tests

002.phpt
--TEST--
Test face detection
--SKIPIF--

--FILE--

--EXPECT--
face detection works



C


:

phpize && ./configure && make

:

make test

DateTime Pattern Generator


, , C++ .
intl. : https://blog.ksimka.io/a-long-journey-to-formatting-a-date-without-a-year-internationally-with-php/#header. , intl , February 10 10 . .

ICU. Debian-like libicu-dev.

config.m4


config.m4

PHP_ARG_ENABLE(intl-dtpg, whether to enable intl-dtpg support,
[  --enable-intl-dtpg           Enable intl-dtpg support])

if test "$PHP_INTL_DTPG" != "no"; then
  PHP_SETUP_ICU(INTL_DTPG_SHARED_LIBADD)
  PHP_SUBST(INTL_DTPG_SHARED_LIBADD)
  PHP_REQUIRE_CXX()

  PHP_NEW_EXTENSION(intl_dtpg, intl_dtpg.cpp, $ext_shared,,-std=c++0x $ICU_INCS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi



. ICU intl , PHP_SETUP_ICU intl .
PHP_NEW_EXTENSION $ICU_INCS ICU .

intl_dtpg.h


intl_dtpg.h
#ifndef INTL_DTPG_H
#define INTL_DTPG_H

#include 
#include 
#include dtptngen.h>

extern "C" {
#include "php.h"
#include "ext/standard/info.h"
}

extern zend_module_entry intl_dtpg_module_entry;
#define phpext_intl_dtpg_ptr &intl_dtpg_module_entry

#define INTL_DTPG_VERSION "1.0.0"

#ifdef ZTS
#include "TSRM.h"
#endif

typedef struct {
    DateTimePatternGenerator *dtpg;
    UErrorCode status;
    zend_object zo;
} IntlDateTimePatternGenerator_object;

static inline IntlDateTimePatternGenerator_object *php_intl_datetimepatterngenerator_fetch_object(zend_object *obj) {
    return (IntlDateTimePatternGenerator_object *)((char*)(obj) - XtOffsetOf(IntlDateTimePatternGenerator_object, zo));
}

#if defined(ZTS) && defined(COMPILE_DL_INTL_DTPG)
ZEND_TSRMLS_CACHE_EXTERN()
#endif

#endif /* INTL_DTPG_H */



IntlDateTimePatternGenerator_object. DateTimePatternGenerator ICU, zend_object, PHP . C++ . API PHP zend_object, , zend_object.

inline IntlDateTimePatternGenerator_object zend_object. zend_object zend_object. , . intl.

intl_dtpg.cpp


:

class IntlDateTimePatternGenerator
{
    /**
     * @param string $locale
     */
    public function __construct(string $locale) {}

    /**
     * Return the best pattern matching the input skeleton.
     * It is guaranteed to have all of the fields in the skeleton.
     *
     * @param string $skeleton The skeleton is a pattern containing only the variable fields.
     *           For example, "MMMdd" and "mmhh" are skeletons.
     * @return string The best pattern found from the given skeleton.
     */
    public function findBestPattern(string $skeleton) {}
}

intl_dtpg.cpp
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "intl_dtpg.h"
#include ustdio.h>
#include smpdtfmt.h>

zend_class_entry *IntlDateTimePatternGenerator_ce;
zend_object_handlers IntlDateTimePatternGenerator_object_handlers;

/* {{{ IntlDateTimePatternGenerator_objects_dtor */
static void IntlDateTimePatternGenerator_object_dtor(zend_object *object)
{
    zend_objects_destroy_object(object);
}
/* }}} */

/* {{{ IntlDateTimePatternGenerator_objects_free */
void IntlDateTimePatternGenerator_object_free(zend_object *object)
{
    IntlDateTimePatternGenerator_object *dtpgo = php_intl_datetimepatterngenerator_fetch_object(object);

    zend_object_std_dtor(&dtpgo->zo);

    dtpgo->status = U_ZERO_ERROR;
    if (dtpgo->dtpg) {
        delete dtpgo->dtpg;
        dtpgo->dtpg = nullptr;
    }
}
/* }}} */

/* {{{ IntlDateTimePatternGenerator_object_create */
zend_object *IntlDateTimePatternGenerator_object_create(zend_class_entry *ce)
{
    IntlDateTimePatternGenerator_object* intern;

    intern = (IntlDateTimePatternGenerator_object*)ecalloc(1,
                        sizeof(IntlDateTimePatternGenerator_object) + zend_object_properties_size(ce));

    zend_object_std_init(&intern->zo, ce);
    object_properties_init(&intern->zo, ce);
    intern->dtpg = nullptr;
    intern->status = U_ZERO_ERROR;

    intern->zo.handlers = &IntlDateTimePatternGenerator_object_handlers;

    return &intern->zo;
}
/* }}} */

/* {{{ proto void IntlDateTimePatternGenerator::__construct(string $locale)
 * IntlDateTimePatternGenerator object constructor.
 */
PHP_METHOD(IntlDateTimePatternGenerator, __construct)
{
    zend_string *locale;
    zval *object;
    IntlDateTimePatternGenerator_object* dtpg = nullptr;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &locale) == FAILURE) {
        return;
    }

    object = getThis();
    dtpg = php_intl_datetimepatterngenerator_fetch_object(Z_OBJ_P(object));

    dtpg->status = U_ZERO_ERROR;
    dtpg->dtpg = DateTimePatternGenerator::createInstance(Locale(ZSTR_VAL(locale)), dtpg->status);
}
/* }}} */

/* {{{ proto string IntlDateTimePatternGenerator::findBestPattern(string $skeleton)
 * Return the best pattern matching the input skeleton.
 */
PHP_METHOD(IntlDateTimePatternGenerator, findBestPattern)
{
    zend_string *skeleton;
    zval *object;
    IntlDateTimePatternGenerator_object* dtpg = nullptr;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &skeleton) == FAILURE) {
        return;
    }

    object = getThis();
    dtpg = php_intl_datetimepatterngenerator_fetch_object(Z_OBJ_P(object));

    UnicodeString pattern = dtpg->dtpg->getBestPattern(UnicodeString(ZSTR_VAL(skeleton)), dtpg->status);

    std::string s;
    pattern.toUTF8String(s);
    RETURN_STRING(s.c_str());
}
/* }}} */

ZEND_BEGIN_ARG_INFO_EX(arginfo_findBestPattern, 0, 0, 1)
    ZEND_ARG_INFO(0, skeleton)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 1)
    ZEND_ARG_INFO(0, locale)
ZEND_END_ARG_INFO()

const zend_function_entry IntlDateTimePatternGenerator_functions[] = {
    PHP_ME(IntlDateTimePatternGenerator, __construct, arginfo___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    PHP_ME(IntlDateTimePatternGenerator, findBestPattern, arginfo_findBestPattern, ZEND_ACC_PUBLIC)
    PHP_FE_END
};

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(intl_dtpg)
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "IntlDateTimePatternGenerator", IntlDateTimePatternGenerator_functions);
    ce.create_object = IntlDateTimePatternGenerator_object_create;
    IntlDateTimePatternGenerator_ce = zend_register_internal_class(&ce);

    memcpy(&IntlDateTimePatternGenerator_object_handlers, zend_get_std_object_handlers(),
        sizeof IntlDateTimePatternGenerator_object_handlers);
    IntlDateTimePatternGenerator_object_handlers.offset =
                    XtOffsetOf(IntlDateTimePatternGenerator_object, zo);
    IntlDateTimePatternGenerator_object_handlers.clone_obj = NULL; //no clone support
    IntlDateTimePatternGenerator_object_handlers.dtor_obj = IntlDateTimePatternGenerator_object_dtor;
    IntlDateTimePatternGenerator_object_handlers.free_obj = IntlDateTimePatternGenerator_object_free;

    if(!IntlDateTimePatternGenerator_ce) {
        zend_error(E_ERROR, "Failed to register IntlDateTimePatternGenerator class");
        return FAILURE;
    }

    return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(intl_dtpg)
{
    return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(intl_dtpg)
{
    php_info_print_table_start();
    php_info_print_table_header(2, "intl_dtpg support", "enabled");
    php_info_print_table_header(2, "intl_dtpg version", INTL_DTPG_VERSION);
    php_info_print_table_end();
}
/* }}} */

/* {{{ intl_dtpg_functions[]
 */
const zend_function_entry intl_dtpg_functions[] = {
    PHP_FE_END
};
/* }}} */

/* {{{ intl_dtpg_module_entry
 */
zend_module_entry intl_dtpg_module_entry = {
    STANDARD_MODULE_HEADER,
    "intl_dtpg",
    intl_dtpg_functions,
    PHP_MINIT(intl_dtpg),
    PHP_MSHUTDOWN(intl_dtpg),
    NULL,
    NULL,
    PHP_MINFO(intl_dtpg),
    INTL_DTPG_VERSION,
    STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_INTL_DTPG
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(intl_dtpg)
#endif



, PHP .

IntlDateTimePatternGenerator_object_dtor PHP . , API.
IntlDateTimePatternGenerator_object_free . , , . , zend_object, ++ .
IntlDateTimePatternGenerator_object_create . intl.
.
PHP_METHOD(IntlDateTimePatternGenerator, __construct) , DateTimePatternGenerator.
, zend_parse_parameters, zend_string , zend_parse_parameters S. PHP 7. s C-style , .
PHP_METHOD(IntlDateTimePatternGenerator, findBestPattern) ICU .
. zend_API.h , .
zend_function_entry . PHP_ME . .
PHP_MINIT_FUNCTION(intl_dtpg) . .
PHP_MSHUTDOWN_FUNCTION(intl_dtpg) shutdown, SUCCESS, , zend_module_entry, NULL.
PHP_MINFO_FUNCTION(intl_dtpg) phpinfo()
zend_function_entry, .
zend_module_entry shutdown , NULL request, shutdown .

tests


, :

001.phpt
--TEST--
Check for intl_dtpg presence
--SKIPIF--

--FILE--

--EXPECT--
d MMMM;MMMM d





phpize && ./configure && make
make test


valgrind


intl_dtpg . ini :

test-php.ini
extension=modules/intl_dtpg.so


php :
test.php

https://habrahabr.ru/post/335478/

:  

: [1] []
 

:
: 

: ( )

:

  URL