preface

In addition to its excellent source code design, PHP also provides a comprehensive Zend Api and extension skeleton interface to provide extension functionality. Based on the extension ability, it is very easy to implement some applications that are difficult to implement or high performance using pure PHP, such as Swoole and other source libraries, etc. This article will deepen the understanding of learning by writing a usable extension through practice.

The environment

  • Mac Big Sur
  • PHP version: 7.3.22
  • Git address: github.com/cooper-li/p…

First, basic expansion

Generating extended skeleton

CD ~/Work/c/php-7.3.22/ext./ ext_kel.php --ext cooper_b --author cooperCopy the code

Modify the config.m4 configuration file

PHP_ARG_ENABLE(cooper_b, whether to enable cooper_b support, Make sure that the comment is aligned: [ --enable-cooper_b Enable cooper_b support], no)Copy the code

Note: config.m4 is used to generate a configure file in conjunction with phpize. The configure file is used for environment detection. Checks whether the environment required to run the extended compilation is met. DNL is the comment symbol. The above code says that if you are writing an extension that relies on other extensions or lib libraries, you need to uncomment the PHP_ARG_WITH code. Otherwise, uncomment the PHP_ARG_ENABLE code segment. We write extensions that do not depend on other extensions or lib libraries. Therefore, we remove the comment before PHP_ARG_ENABLE.

Perform compilation and installation

/Work/c/php73/bin/phpize - with - PHP - config = / Users / / Work/cooper c/php73 / bin/PHP - config # installed make sudo make install # after the completion of the prompt: Installing shared extensions: /Users/cooper/Work/c/php73/lib/php/extensions/debug-non-zts-20180731/Copy the code

Add extensions

Vim XXX/PHP. Ini extension=cooper_bCopy the code

View extension

# test file, default generated function <? php $a = cooper_b_test1(); $b = cooper_b_test2("cooper"); var_dump($a, $b); The extension cooper_b is loaded and working! string(11) "Hello World"Copy the code

Two, realize the order number

  • The previous steps have generated the base extension, but generating the order number extension requires us to add our own methods

Write the file in ext/cooper_b: order.c

#include <stdio.h>
#include<sys/time.h>

/ / left - > right
// 64 --> 25: 40 bit timestamp difference
// 24 --> 11: 13-bit service zone: 8192 services
// 1 --> 10: 10 bits autoincrement ID: (1024 * 1000)/s Theoretical value


typedef unsigned long long uint64_t;

const long ORDER_TIME_BIT = 0x1fff;
const long ORDER_SORT_BIT = 0x2ff;
const uint64_t START_TIME = 1598889600000; / / 2020-09-01
int incrNum = 0;

struct OrderNumInfo {
    uint64_t ts_c;
    int bid_c;
    int incrid_c;
};

// Get the millisecond timestamp
uint64_t getMillTs(a) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
}

// Generate the order number
// Parameter service ID
uint64_t genOrderNum(int bid) {
    uint64_t orderNum;
    uint64_t millTs;
    int businessPart;
    uint64_t tsPart;
    long tsReduce;

    // The timestamp part
    millTs = getMillTs();
    // printf(" current time is: %llu \n", millTs);
    tsReduce = millTs - START_TIME;
    // printf(" time difference: %ld \n", tsReduce);
    tsPart = tsReduce << 23;

    // Business ID section
    businessPart = bid << 10;

    // The increment part
    incrNum++;

    / / assembly
    orderNum = (tsPart | businessPart | incrNum);
    return orderNum;
}

// Parse the order number
struct OrderNumInfo parseOrderNum(uint64_t orderNum)
{
    uint64_t ts;
    int bid;
    int incrNum;
    struct OrderNumInfo ret;

    // Get the timestamp
    ts = orderNum >> 23;

    // Obtain the service ID
    bid = orderNum >> 10 & ORDER_TIME_BIT;

    // Get the self-added ID
    incrNum = orderNum & ORDER_SORT_BIT;

    ret.ts_c = (ts + START_TIME);
    ret.bid_c = bid;
    ret.incrid_c = incrNum;

    return ret;
}
Copy the code

Modify the cooper_B.c file to add the methods we need

  1. Header file import
#include "order.c"
Copy the code
  1. Add two methods under the PHP_FUNCTION(cooper_b_test2) method
/* {{{ int cooper_a_genOrder( [ int $var ] ) */
PHP_FUNCTION(cooper_a_genOrder)
        {
                zend_long bid;
        zend_long retval;

        ZEND_PARSE_PARAMETERS_START(1.1)
        Z_PARAM_LONG(bid)
        ZEND_PARSE_PARAMETERS_END();
        retval = genOrderNum(bid);
        RETURN_LONG(retval);
        }
/ * * /}}}

/* {{{ string cooper_a_parseOrder( [ long $var ] ) */
PHP_FUNCTION(cooper_a_parseOrder)
        {
                struct OrderNumInfo ret;
                uint64_t orderNum;

                ZEND_PARSE_PARAMETERS_START(1.1)
                Z_PARAM_LONG(orderNum)
                ZEND_PARSE_PARAMETERS_END();

                ret = parseOrderNum(orderNum);

                RETURN_STR(strpprintf(0."Time => %llu, serial number => %d, increment => %d", ret.ts_c, ret.bid_c, ret.incrid_c));
        }
/ * * /}}}
Copy the code
  1. Add two arguments to the /* {{{arginfo */ comment section
ZEND_BEGIN_ARG_INFO(arginfo_cooper_a_genOrder, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_cooper_a_parseOrder, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
Copy the code
  1. Register functions in the array: cooper_b_functions, resulting in:
static const zend_function_entry cooper_b_functions[] = {
	PHP_FE(cooper_b_test1,		arginfo_cooper_b_test1)
	PHP_FE(cooper_b_test2,		arginfo_cooper_b_test2)
    PHP_FE(cooper_a_genOrder,		arginfo_cooper_a_genOrder)  
    PHP_FE(cooper_a_parseOrder,		arginfo_cooper_a_parseOrder)
	PHP_FE_END
};
Copy the code
  1. Once this function development is complete, repeat the compile installation in step 1 to reload the extension
  2. Write script tests, test scripts

      

$a = cooper_b_test1();
$b = cooper_b_test2();
var_dump($a.$b);
$c = cooper_a_genOrder(111);
$d = cooper_a_parseOrder($c);

var_dump($c.$d);

// Get the time
$t = substr($d.10.13);
var_dump($t);

$c = cooper_a_genOrder(Awesome!);
$d = cooper_a_parseOrder($c);
Copy the code

The script output

The extension cooper_b is loaded and working! String (11) "Hello World" int(40969617455299585) String (51) "time => 1603773558990, serial number => 111, NULL String (11) "Hello World" int(40969617455867906) String (51) "Time => 1603773558990, serial number => 666, increment => 2"Copy the code

Reference:

Yuerblog.cc /wp-content…

Fish: yuerblog. Cc / 2017/07/11 /…