PHP conversion Lunar C extension development

Source: Internet
Author: User
PHP conversion Lunar C extension development this article is mainly to familiarize yourself with PHP extension development, development of a lunar extension seems useless luan. One of the reasons for PHP's success is that it has powerful extensions and allows developers to flexibly develop their own PHP extensions. I am dedicated to becoming an LNMP Stack Expert (I accidentally installed B). of course, I cannot miss it. I still have a lot of knowledge to study !!

PHP extension development extension function definition file

Define a function definition file first, which is much simpler than thrift's IDL file. The function definition file defines the extended function prototype. The general format is a function row. The function definition needs to specify the return value and input parameter types, including: bool, float, int, array, and so on. The function definition file issued by lunar calendar is as follows:

String datetolunar (int year, int month, int day );

Of course, you can also define multiple functions in the same function definition file, or define a class, so that the corresponding function class extension skeleton can be generated. For example:

Class Lunar {

String datetolunar (int year, int month, int day );

}

Generate PHP extension skeleton

The ext/directory under the PHP source code directory contains the ext_skel script. It can be used to generate an extension skeleton based on the defined lunar extension function definition file lunar. skel.

~ #./Ext_skel-extname = datetolunar-proto = lunar. skel

Extname indicates the generated extension name. after execution, the datetolunar directory is generated under the ext/directory.

Tiger history php-5.6.17/ext/datetolunar» ls [14:44:36] credits experimental config. m4 config. w32 datetolunar. c datetolunar. php php_datetolunar.h tests

To enable compilation of the extension, you need to modify the config. m4 file and remove the comments (dnl) on the shrimp surface)

PHP_ARG_WITH (datetolunar, for datetolunar support,

Dnl Make sure that the comment is aligned:

[-With-datetolunar Include datetolunar support])

Dnl Otherwise use enable:

PHP_ARG_ENABLE (datetolunar, whether to enable datetolunar support,

Dnl Make sure that the comment is aligned:

[-Enable-datetolunar Enable datetolunar support])

If no external C library is referenced, you do not need to change it too much. Otherwise, you may need to understand these

PHP_ADD_INCLUDE

PHP_ADD_LIBRARY_WITH_PATH

PHP_SUBST

PHP_NEW_EXTENSION

Google.

Compile

Now you can compile this extension to your PHP (although there is no function ). I usually choose the dynamic compilation method. most open-source PHP extensions will also use this method because it is simple.

~ # Phpize

~ #./Configure-with-php-config =/opt/php/bin/php-config

~ # Make

~ # Make install

Then the datetolunar. so file is generated and added to php. ini to add extension = datetolunar. so, you can try to call this extension. The generated skeleton code contains the PHP file for testing the extension and checks whether the extension has been compiled to PHP.

Tiger history php-5.6.17/ext/datetolunar» php datetolunar. php [14:31:26]

Functions available in the test extension:

Confirm_datetolunar_compiled

Datetolunar

Congratulations! You have successfully modified ext/datetolunar/config. m4. Module datetolunar is now compiled into PHP.

Write C code

After introducing the PHP extension development process, let's look at how to implement a lunar extension. We may need to know about the lunar calendar algorithm first.

Understanding lunar Calendar algorithms

Basic knowledge of lunar computing and development

-Algorithm series: computing the Chinese lunar calendar (1)

-Algorithm series: computing the Chinese lunar calendar (2)

Open the datetolunar. c file and you can see the following hex_lunar definition.

Static int hex_lunar [] = {

0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,

0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,

....

};

Each hexadecimal number is represented from January 1, 1900 ~ For all lunar data in 2050, hexadecimal is converted into binary. each part is represented as follows:

1-4: indicates whether a leap year exists in the current year. if yes, it is the month of the leap month. If no, it is 0.

5-16: indicates whether a month is a large month or a small month except a leap month. 1 is 30 days, and 0 is 29 days.

Note: from January 1, 16th to January 1, 5th.

17-20: indicates whether a leap month is a large month or a small Month. it makes sense only when a leap month exists.

For example:

The data for January 1, 1980 is 0x095b0.

Binary: 0000 1001 0101 1011 0000

Indicates that there is no leap month in 1980. the number of days from January to December is: 30, 29, 29, 30, 30, 30, 30, 30, 30.

The data for April 1982 is 0x0a974.

0000 1010 0 1001 0111 0100

It indicates that July 22, is a leap month, that is, the second month of July 22, and it is a small month of growth.

The number of days from January to 13 months is: 30, 29, 30, 29, 29 (leap month), 30, 29, 29, 30, 29, 29, 30, 30.

Code writing and debugging

I am not familiar with writing PHP extensions at the beginning. I chose to write and debug the function, and then copy the code to the PHP extension. C-language debug: cgdb is recommended. it is much easier than gdb to view code and debug.

Compile

~ # Gcc-g lunar. c-o lunar

Use cgdb for debugging

~ # Sudo cgdb lunar

Break-set breakpoints

Run-run the program

Print-print variables

Continue-continue execution

PS: if the printed array is long and print is abbreviated, you can use

> Set print element 0

.

Migrating code to PHP extension

After the C code is written and there is no problem, you are ready to migrate it to the PHP extension. The automatically generated c function PHP_FUNCTION (datetolunar) is defined in the skeleton code datetolunar. C generated by the ext_skel script.

/* {Proto string datetolunar (int year, int month, int day)

;*/

PHP_FUNCTION (datetolunar)

{

Int argc = ZEND_NUM_ARGS ();

Long year;

Long month;

Long day;

If (zend_parse_parameters (argc TSRMLS_CC, "lll", & year, & month, & day) = FAILURE) return;

Php_error (E_WARNING, "datetolunar: not yet implemented ");

}

/*}}}*/

To obtain the parameters passed by the function, you can use the zend_parse_parameters () API function. The following is a prototype of the function:

Zend_parse_parameters (int num_args TSRMLS_DC, char * type_spec ,...);

The first parameter is the number of parameters passed to the function. The common practice is to pass it ZEND_NUM_ARGS (). This is a macro that indicates the total number of parameters passed to the function. The second parameter is used to ensure thread security and always transmits the TSRMLS_CC macro. The third parameter is a string that specifies the expected parameter type of the function, followed by the list of variables that need to be updated with the parameter value. Because PHP uses loose variable definitions and dynamic type determination, it is possible to convert parameters of different types into the expected type. For example, if you pass an integer variable and the function requires a floating point number, zend_parse_parameters () automatically converts the integer to the corresponding floating point number. If the actual value cannot be converted to the expected type (such as integer to array), a warning is triggered.

After learning about this, copy the written C code to the function. All we need to do is let PHP return the desired results.

Return values from PHP functions

Returns a string. the function we use is RETURN_STRING.

Char * ret = lunar_output; RETVAL_STRINGL (lunar_output, strlen (ret), 1 );

This directly returns a static string. if the last parameter is set to 0, an error occurs when php returns the free string. Because PHP is a type-safe scripting language, php will free up the strings returned by RETURN_STRINGL or RETURN_STRING when appropriate. Therefore, the programmer must ensure that the returned strings are in the heap and free up, this is why dynamic allocation is okay. And:

Char * ret = "hello world"; RETURN_STRINGL (ret, strlen (ret), 0 );

This directly returns a static string, causing an error when PHP returns the free string. RETURN_STRINGL and RETURN_STRING are the last parameters. if the value is 1, a copy of the string in the first parameter is copied and returned in the heap.

The extended API contains a wide range of macros used to return values from functions. These macros have two main styles: The first is the RETVAL_type () form, which sets the return value but the C code continues to execute. This is usually used when you want to clean up the control before handing it over to the script engine, and then use C's return statement "return" to return to PHP; the latter macro is more common in the form of RETURN_type (). it sets the return type and controls the return to PHP. The following table explains most existing macros.

Set the return value and end the function Set return value Macro return type and parameters
RETURN_LONG (l) RETVAL_LONG (l) Integer
RETURN_BOOL (B) RETVAL_BOOL (B) Boolean (1 or 0)
RETURN_NULL () RETVAL_NULL () NULL
RETURN_DOUBLE (d) RETVAL_DOUBLE (d) Floating point number
RETURN_STRING (s, dup) RETVAL_STRING (s, dup) String. If dup is 1, the engine will call estrdup () to duplicate s and use copy. If dup is 0, s is used.
RETURN_STRINGL (s, l, dup) RETVAL_STRINGL (s, l, dup) String value with a length of l. Similar to the previous macro, but the speed is faster because the length of s is specified.
RETURN_TRUE RETVAL_TRUE Returns a boolean value of true. Note that this macro has no parentheses.
RETURN_FALSE RETVAL_FALSE Returns a boolean value of false. Note that this macro has no parentheses.
RETURN_RESOURCE (r) RETVAL_RESOURCE (r) Resource handle.
WORK DONE

This completes our PHP lunar extension. Compiled successfully !!! (Of course, there may be problems in make. it is good to solve them one by one)

Test

Tiger pull work/github/php-lunar-extension» php-r "echo datetolunar (, 27);" [14:47:19] Bing Shen [monkey] lunar January 20%

OK, Good ~

Performance testing

Implement the same function of the lunar conversion code. The first is the lunar function implemented by php, and the second is the PHP extension we just implemented, which has been executed 10000 times, and the performance has improved by about 86 times (slightly excited ~).

Tiger pull work/github/php-lunar-extension» php test. php [18:28:06]

> Excute php function.

1.7234871387482

> Excute php extension function.

0.022943019866943

The extension code is here: https://github.com/jixiaod/php-lunar-extension

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.