Php-cpp Development Extension (v)

Source: Internet
Author: User
Tags export class zend

Php-cpp is a C + + library for developing PHP extensions. This section explains how to implement PHP classes in C + +.

Class and object classes and objects

How do you write PHP classes in php-cpp? Very simple, see the following example:
main.cpp

/** * User: Public number: Feihong Shadow's Blog (fhyblog) * DATE:2018/7 * * #include <time.h> #include <phpcpp.h>/** * Counter class tha     T can is used for counting */class counter:public php::base{private:/** * The initial value * @var int    */int _value = 0;public:/** * C + + constructor and destructor */Counter () = default;    Virtual ~counter () = default;     /** * Update methods to increment or decrement the counter * Both methods return the NEW value of the counter    * @return int */Php::value increment () {return ++_value;}    Php::value Decrement () {return--_value;} /** * Method to retrieve the current counter value * @return int */Php::value value () const {return _va Lue }//static member function of the class static Php::value gettime () {return time (NULL);}};/  * * Switch to C context to ensure, the Get_module () function * is callable by C programs (which the Zend engine is) */extern "C" {/** * Startup functioN that's called by the Zend engine * To retrieve all information about the extension * @return void* * * Phpcpp_export void *get_module () {///must be a static type because the extension object needs to reside in the PHP process in memory static php::extension Extension ("                HelloWorld "," 1.0.0 ");                Initialize the Export class php::class<counter> Counter ("Counter");        The accessible normal function counter.method<&counter::increment> ("increment") of the registered export class;        Counter.method<&counter::d ecrement> ("decrement");                Counter.method<&counter::value> ("value");        Registers an accessible static function counter.method<&counter::gettime> ("gettime") for the exported class;                Register export class, use Rvalue reference method, optimize resource using Extension.add (Std::move (counter));    Returns the extended object pointer return extension; }}

First, the C + + class must inherit from, and Php::Base Secondly, when we add the class to the extension object, we must also specify all the methods to be accessed from PHP, and finally the export class.

Let's test first:

/** * User: 公众号: 飞鸿影的博客(fhyblog) * Date: 2018/7 */$counter = new Counter;echo 'result of increment() = '. $counter->increment() . PHP_EOL;echo 'result of increment() = '. $counter->increment() . PHP_EOL;echo 'result of decrement() = '. $counter->decrement() . PHP_EOL;echo 'result of value() = '. $counter->value() . PHP_EOL;echo 'result of gettime() = '. Counter::gettime() . PHP_EOL;

Output:

result of increment() = 1result of increment() = 2result of decrement() = 1result of value() = 1result of gettime() = 1531621728
Access modifiers

We can also add an access modifier to the exported method:

//初始化导出类Php::Class<Counter> counter("Counter");//注册导出类的可访问普通函数counter.method<&Counter::increment> ("increment", Php::Private, {    Php::ByVal("a", Php::Type::Numeric)});counter.method<&Counter::decrement> ("decrement", Php::Protected, {    Php::ByVal("a", Php::Type::Numeric)});counter.method<&Counter::value> ("value");

Php::Class::methodThe second parameter supports setting the access modifier, which is public by default, and the third parameter, like a normal function, supports setting the parameter type.

Supported access modifiers:

extern PHPCPP_EXPORT const int Static;extern PHPCPP_EXPORT const int Abstract;extern PHPCPP_EXPORT const int Final;extern PHPCPP_EXPORT const int Public;extern PHPCPP_EXPORT const int Protected;extern PHPCPP_EXPORT const int Private;extern PHPCPP_EXPORT const int Const;

One thing to note: The methods to be exported in C + + must all be public, even if we mark them as private or protected in PHP. Because the methods we write are called by the Php-cpp library, if they are set to private, they will not be visible to the library.

Abstract class, Final class

Declaring the class as final is simple, just declare it when you initialize the Export class:

Php::Class<Counter> counter("Counter", Php::Final);

So how do you declare an abstract class? In the above example Php::Class::method , the address of the real C + + method is passed in, but the abstract method is usually not implemented, so how do we provide pointers to methods? Fortunately, registering an abstract method in Php-cpp does not provide pointers to the C + + method.

Example:
Abstract class Original declaration:

/** * User: 公众号: 飞鸿影的博客(fhyblog) * Date: 2018/7 */#include <phpcpp.h>//类声明class MyAbstract : public Php::Base{};extern "C" {        PHPCPP_EXPORT void *get_module()     {        // 必须是static类型,因为扩展对象需要在PHP进程内常驻内存        static Php::Extension extension("helloworld", "1.0.0");                //初始化导出类        Php::Class<MyAbstract> my_abstract("MyAbstract", Php::Abstract);                //注册抽象方法:如果不给出C++方法的地址,该方法自动变成抽象方法        my_abstract.method("myAbstractMethod", {             Php::ByVal("a", Php::Type::String, true)         });                extension.add(std::move(my_abstract));                // 返回扩展对象指针        return extension;    }}

We tried to instantiate the class in test.php MyAbstract , prompting:

PHP Fatal error:  Uncaught Error: Cannot instantiate abstract class MyAbstract

Note: The official example in the initialization of the export class is not added Php::Abstract , the test when the discovery can still be instantiated, just call the abstract method to error.

Constructors and destructors

In C + + code, PHP's constructors and destructors are essentially common methods. Understand this, it is not difficult to achieve.

Example:

/** * User: Public number: Feihong Shadow's Blog (fhyblog) * DATE:2018/7 * * #include <phpcpp.h>/** * Simple counter class */class Counter:p Ublic php::base{private:/** * Internal value * @var int */int _value = 0;public:/** * C + + C    Onstructor */Counter () = default;    /** * C + + destructor */virtual ~counter () = default; /** * php "constructor" * @param params */void __construct (php::P arameters &params) {//    Copy first parameter (if available) if (!params.empty ()) _value = Params[0];    }/** * functions to increment and decrement */Php::value increment () {return ++_value;}    Php::value Decrement () {return--_value;} Php::value Value () const {return _value;}};/ * * Switch to C context so, the Get_module () function can be * Called by C programs (which the Zend engine is) */ex Tern "C" {/** * Startup function for the extension * @return void* */Phpcpp_export VoiD *get_module () {static php::extension myextension ("My_extension", "1.0"); Description of the class so, PHP knows which methods are accessible php::class<counter> Counter ("Count        Er ");        Counter.method<&counter::__construct> ("__construct");        Counter.method<&counter::increment> ("increment");        Counter.method<&counter::d ecrement> ("decrement");        Counter.method<&counter::value> ("value");        Add the class to the extension Myextension.add (Std::move (counter));    Return the extension return myextension; }}

If a constructor is required to be private, simply add a flag at the time of registration:

counter.method<&Counter::__construct>("__construct", Php::Private);

If you want to disable clone, you can:

// alternative way to make an object unclonablecounter.method("__clone", Php::Private);
Interface

Interface (Interface) because it does not require implementation of a specific method, we can do so in a manner similar to defining the class. The only difference is that we do not use Php::Class<YourClass> , but an Php::Interface instance.

//初始化Php::Interface interface("MyInterface");//添加成员方法interface.method("myMethod", {     Php::ByVal("value", Php::Type::String, true) });//注册到扩展extension.add(std::move(interface));
Inheriting implement implementations

In addition to the PHP code we can implement the interface or inherit the class, can also be implemented in C + +. The Php::Class<YourClass> object has extends() an implements() interface that can be used to specify the base class and implementation. We need to pass in the previously configured class or interface. Let's look at an example.

/** * User: Public number: Feihong Shadow's Blog (fhyblog) * DATE:2018/7 * * #include <phpcpp.h> #include <iostream>class myclass:public php::base{public:php::value MyMethod (Php::P arameters &params) {php::out << "MyClass" &lt            ;< Std::endl;        return params; }};extern "C" {phpcpp_export void *get_module () {static php::extension Extension ("HelloWorld", "1.0.0"                );        Define the interface Php::interface Interface ("MyInterface");        Interface.method ("MyMethod", {php::byval ("value", Php::type::string, True)});        Extension.add (Std::move (interface));        Registering a custom class php::class<myclass> MyClass ("MyClass");        Implement Interface Definition myclass.implements (interface);         Myclass.method<&myclass::mymethod> ("MyMethod", {php::byval ("value", php::type::string, True)        });                Extension.add (Std::move (MyClass));    Returns the extended object pointer return extension; }} 

Test:

$obj = new MyClass();var_dump($obj->myMethod(11));
Extends inheritance

The inheritance of PHP is not directly related to C + + inheritance, and must be displayed using Php::Class::extends() inheritance.

And then the above example shows.

/** * User: Public number: Feihong Shadow's Blog (fhyblog) * DATE:2018/7 * * #include <phpcpp.h> #include <iostream>class myclass:public php::base{public:php::value MyMethod (Php::P arameters &params) {php::out << "MyClass" &lt            ;< Std::endl;        return params; }};class mysubclass:public Php::base{};extern "C" {phpcpp_export void *get_module () {static php::ext                Ension extension ("HelloWorld", "1.0.0");        Define the interface Php::interface Interface ("MyInterface");                Interface.method ("MyMethod", {php::byval ("value", Php::type::string, True)});        Registering a custom class php::class<myclass> MyClass ("MyClass");        Implement Interface Definition myclass.implements (interface);         Myclass.method<&myclass::mymethod> ("MyMethod", {php::byval ("value", php::type::string, True)                });        Php::class<mysubclass> MySubClass ("MySubClass"); Mysubclass.extends (MYclass);        Extension.add (Std::move (interface));        Extension.add (Std::move (MySubClass));                Extension.add (Std::move (MyClass));    Returns the extended object pointer return extension; }}

Note: the Registration Class ( extension.add ) needs to be placed behind the extends method, that is, the parent class cannot be registered before using extends, otherwise it cannot be inherited. It is recommended to put the registration on the final side when actually programming.

Magic method

In the Php-cpp, only the __construct() display of the get_module() registration, other magic methods like __get() , __set() , __call() etc. do not need to register.

/** * User: Public number: Feihong Shadow's Blog (fhyblog) * DATE:2018/7 * * * #include <phpcpp.h>/** * A Sample class, that have some pseudo pro Perties that map to native types */class user:public php::base{private:/** * Name of the User * @var St    d::string */std::string _name; /** * Email Address of the user * @var std::string */std::string _email;public:/** * C + + con    Structor and C + + DESTRUCTPR * * User () = default;    Virtual ~user () = default; /** * Get access to a property * @param name name in the property * @return Value Property va Lue */Php::value __get (const php::value &name) {//Check if the property name is supported I        F (name = = "Name") return _name;        if (name = = "Email") return _email;    Property isn't supported, fall back on default return Php::base::__get (name);   }/** * Overwrite a property * @param name Name of the property  * @param value New property value */void __set (const php::value &name, const php::value &value)  {//Check the property name if (name = = "Name") {//store member _name =        Value.stringvalue (); }//We check emails for validity else if (name = = "Email") {//store the email in a stri            ng std::string email = value; Must has a ' @ ' character in it if (Email.find (' @ ') = = Std::string::npos) {//EM            AIL address is invalid, throw exception throw php::exception ("Invalid email address");        }//Store the member _email = email; }//Other properties fall back to default else {//call default php::base::__        Set (name, value); }}/** * Check If a property was set * @param name Name of the property * @return BOOL */bool __isset (const Php::value &name) {//True for name and email address if ( name = = "Name" | |        name = = "Email") return true;    Fallback to default return Php::base::__isset (name); }/** * Remove a property * @param name Name of the property to Remove */void __unset (const P         Hp::value &name) {//name and email can not be unset if (name = = "Name" | | name = "email") {//Warn the user with a exception that this is impossible throw php::exception ("Name and email ad        Dress can not be removed ");    }//fallback to default Php::base::__unset (name);  }};/** * Switch to C context to ensure, the Get_module () function * is callable by C programs (which the Zend engine is) */extern ' C ' {/** * Startup function that's called by the Zend engine * to retrieve all information a     bout the extension * @return void**/Phpcpp_export void *get_module () {//Extension object static php::extension myextension ("My_extension        "," 1.0 "); Description of the class so, PHP knows//which methods is accessible php::class<user> User ("        User ");        Add the class to the extension Myextension.add (std::move (user));    Return the extension return myextension; }}

Test:

<?php/** * User: 公众号: 飞鸿影的博客(fhyblog) * Date: 2018/7 */// initialize user and set its name and email address$user = new User();$user->name = "John Doe";$user->email = "[email protected]";// show the email addressecho($user->email."\n");// remove the email address (this will cause an exception)unset($user->email);?>

(not to be continued)

Want to be the first time to get the latest news, welcome to pay attention 飞鸿影的博客(fhyblog) to, not regularly for you to present technical dry.

Php-cpp Development Extension (v)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.