Write php extensions in c on windows

Source: Internet
Author: User
In windows, use c to write php extensions (to convert) in windows and use c to write php extensions (to encrypt and decrypt php source code). first try helloworld. Download the php source code package. the ext directory is the extension directory, which contains two important files: ext_skel and ext_skel_win32.php. Download cygwin. with this, you can easily create php extensions in windows. Downloading ...... Download php extensions written in c in windows)

Use c to write php extensions in windows (encrypt and decrypt php source code)


Try it with hello world first.
Download the php source code package. the ext directory is the extension directory, which contains two important files: ext_skel and ext_skel_win32.php.
Download cygwin. with this, you can easily create php extensions in windows.
Downloading ......
After the download, use php ext_skel_win32.php -- extname = hello to compile and generate our extended development directory hello, and then write the test program hello world. Add the function definition and function registration statement to the hello. c file:
Function registration statement:

Const zend_function_entry hello_functions [] = {PHP_FE (confirm_hello_compiled, NULL) PHP_FE (sayHello, NULL) // This sentence is manually added {NULL, NULL, NULL }};

?

Function definition:

PHP_FUNCTION(sayHello){ php_printf("Hello C extension");}

?

It seems that it must be in the macro format of PHP_FUNCTION, because a name conflict or other conflicts may occur if you directly write c code in bare mode. Then add the function declaration statement in php_hello.h:
PHP_FUNCTION (sayHello );
Write the test program and the compilation result is as follows:
../Main/config. w32.h ': No such file or directory
I checked it online. it seems that I want to download additional packages... Trouble!
Http://www.php.net/extra/bindlib_w32.zip
Http://www.php.net/extra/win32build.zip
Put these two packages together. I put them under the win32/build directory, and then execute buildconf under the root directory of the php source package. bat (it is best to run in the command line, otherwise the display results will flash ).
Then, set the directory of bison.exe (in the downloaded package) to an environment variable and run configure. bat. The/main/config. w32.h file is generated.
Then, a big push error occurs in the result of compiling the hello project again.
Shape:
... \ Main \ streams/php_stream_transport.h (85): error C2143: syntax error: missing ') 'before '*'
... \ Main \ streams/php_stream_transport.h (85): error C2081: 'Len Len _ t': name in formal parameter list illegal

I can't find the macro definition on the internet. it should be because the socklen_t macro is not defined. but what should I do with the specific macro definition? I can't just write one, so open it.
\ Main \ streams/php_stream_transport.h
It should be a Type alias and an int, because socklen_t addrlen; addrlen should be the storage length value literally.
So add
Typedef int socklen_t;
Save and compile the project just now. There are many fewer errors, but there are still seven. after checking, it is found that the Chinese characters are entered. Correct and then compile... There is another error:
LINK: fatal error LNK1181: cannot open input file "php5ts. lib"
So I will find the php5ts. lib file and put it in the project directory or the default search directory of the VC6 lib file. Find and find...
Tmd, which has not been found in windows search for a long time. Baidu refers to php binary code package. So first, the next binary code package of the same version (it should be the package that must be downloaded by php at ordinary times)
Let's talk about the next environment: windows + vc6 + php5.3.5 (binary code package and source code package) + cygwin
Download completed. find, copy, compile, and succeed!
But there was a very serious problem. The dll file didn't come out. I cried! Php_hello.exp and php_hello.lib are created. How can it be static ??
Actually, it has been generated, but it is not in the Release_TS directory under this directory, but in the Release_TS directory at the ext upper level.
Then test. Haha, is there any way that the tested php version is different from the expanded php version?
If you test it, no. if you restart apache by setting in ini to load php_hello.dll, the error of unreadable memory will occur.
I always think there is no problem with the code, but there should be a problem during the previous compilation configuration.
After some tests, I found that the php binary package was wrong, and the vc9 should be vc6.

Next we will start writing encryption and decryption. Encryption and decryption algorithms are not the focus here. the focus is on how to program on the zend layer using the zend interface in combination with c, decrypt the file before zend compiles the source file (of course, the file must have been encrypted before ).
For ease of use. My idea is to generate an encrypted executable file while generating a dll like php_screw. the encrypted executable file is manually executed and passed in directory parameters, all files in this directory can be encrypted.
After finding a bunch of documents on the Internet, you can check the php_screw code. it is still difficult, so I decided to write it based on my own ideas. Of course, the php_screw code will be used for reference in some places.
First, write a function to decrypt the file. This function uses our existing decryption algorithm to decrypt the file content.
This function should have a parameter that is used to receive the handle of the current request File (it looks like zend_compile_file, Baidu Zhizhi). check whether several articles are called function pointers, the source code is indeed a function pointer)

extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);

?

So how can we get the file pointer of the current request file? It may be related to the role of the zend_compile_file function pointer. Found in the source code:
Zend_compile_file = compile_file;
This function is defined in zend_language_scanner.c. However, it is difficult to understand this function:
-------------
Zend_compile_file is responsible for compiling the script file to be executed into op codes consisting of the basic command sequence of ZE.
PHP performs the following four steps to execute this code:
1. Scanning (Lexing) converts PHP code into a language snippet (Tokens)
2. Parsing: converts Tokens into a simple and meaningful expression.
3. Compilation: compile the expression into Opocdes
4. Execution: execute Opcodes one by one at a time to implement the PHP script function.
-------------
Therefore, we should decrypt the file before the four steps.
The idea is to rewrite a function myCompile to determine to decrypt the file before it is compile, and then call the default complie function. After myCompile is defined, myCompile should be passed to the function pointer zend_compile_file during request initialization.

PHP_MINIT_FUNCTION (dencrypt) {old_comlie_file = compile; // keep the default compile so that you can call volume = myCompile; return SUCCESS;} ZEND_API zend_op_array * myCompile (Volume * file_handle, int type TSRMLS_DC) {// here TSRMLS_DC is a macro similar ,... (The macro definition cannot be found at the moment.) in short, it is related to the thread security of global variables in multi-threaded environments. in the future, we will further investigate // Here we will decrypt the code... Old_comlie_file (file_handle );....}

?
But the problem still persists, because we still don't know how to get the file pointer. I think the decryption steps in php_screw are quite long. For more information, see... Found:

fp = fopen(file_handle->filename, "r");

? It turns out that file_handle contains information about the file name (in fact, if you find the file_handle struct definition statement, you will know ). But there is another section in php_screw:

Char fname [32]; memset (fname, 0, sizeof fname); if (zend_is_executing (TSRMLS_C )) {// TSRMLS_C obtain the global variable // Obtain the name of the currently called function (currently called function? Where is the function? Php functions? Think about the functions in zend. Instead of functions at the php layer, because they have not been compiled yet and are not executed yet.) if (get_active_function_name (TSRMLS_C) {strncpy (fname, get_active_function_name (TSRMLS_C ), sizeof fname-2) ;}} if (fname [0]) {if (strcasecmp (fname, "show_source ") = 0 // that is to say, if these two functions are currently used, they will not be decrypted or compiled. Well, that's right. | Strcasecmp (fname, "highlight_file") = 0) {return NULL ;}}

?

Therefore, this section is necessary. Otherwise, the above two functions cannot be implemented. the compile_file function should also have this step. Therefore, the ciphertext is directly displayed instead of being decrypted.
There is another paragraph:

Fp = fopen (file_handle-> filename, "r"); if (! Fp) {// If opening fails, call the default compile function return org_compile_file (file_handle, type);} fread (buf, PM9SCREW_LEN, 1, fp ); // the function of the following five sentences is: if an unencrypted file is found, it will not be decrypted. If (memcmp (buf, PM9SCREW, PM9SCREW_LEN )! = 0) {fclose (fp); return org_compile_file (file_handle, type);} if (file_handle-> type = ZEND_HANDLE_FP) fclose (file_handle-> handle. fp); // Determine the file handle type and apply the corresponding close function. If (file_handle-> type = ZEND_HANDLE_FD) close (file_handle-> handle. fd); file_handle-> handle. fp = pm9screw_ext_fopen (fp); // call the file decryption function and use the fp in file_handle to receive the result file_handle-> type = ZEND_HANDLE_FP; // Set the handle type to the file pointer type file_handle-> opened_path = expand_filepath (file_handle-> filename, NULL TSRMLS_CC );

?

I cannot understand the above sentence. I wonder if I accept the path of the current file? One trace finds the expand_filepath_ex function. The last sentence of this function is return real_path. it seems that it is to return the path of the file to be compiled. But why the above two steps? Set the type and path. If we do not perform the decryption operation, we do not need to perform these two steps. I guess it is because fclose (file_handle-> handle. fp) has changed the file_handle status, so we need to reset it! (But there is a question: is it decrypted before Compilation or before Scanning? I initially thought that it was decrypted before Compilation in terms of semantics, but it should be decrypted before Scanning from the actual situation. it can be verified later here. it turns out that the latter is correct, because the compile_file function calls the open_file_for_scanning function, that is to say, the compile_file function executes the 123 step mentioned above ).
The entry point is available (and the problem of 3 out of 4 needs to be solved ).

?

Next, start the function for writing and decrypting files.
You need to consider the following: the plaintext code after the file is decrypted does not need to be written into the file. how can we obtain these plaintext file pointers? Using temporary files? However, if each request uses a different temporary file, many temporary files will be generated (obviously unavailable). if only one temporary file is used for different requests to the same PHP file, there will also be resource waiting issues (obviously not feasible ). Can I directly specify a file pointer in the memory? Let's take a look at the php_screw practice and call tmpfile () to generate a temporary file, but it will be automatically deleted when the program exits! In fact, I think files in the memory are also implemented in this way.
Directly implement the reversible encryption and decryption algorithm previously written in php using c, but c does not have the md5 and base64 functions available. it seems that only the two functions can be abandoned.
After writing the code, you can start compiling and modify some errors.
Then an error occurs during the link:
Error LNK2001: unresolved external symbol _ zend_compile_file
After searching, it seems that the function cannot be found because of different function compilation methods. add:

BEGIN_EXTERN_C()ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);END_EXTERN_C()

?

You can.
The dll file is successfully generated, but you do not know how to generate the executable file for encryption. of course, the simplest solution is to create another project. It seems that we have to do this first, because we are not very familiar with some of vc's compilation mechanisms and parameter settings (it seems that we will talk about this in the future ).
Then I encountered the pointer passing problem in c (I haven't figured it out for a long time, I forgot some basics, and finally I used the second-level pointer to solve the problem of returning the pointer as a parameter ).
The _ zend_compile_file symbol cannot be found during the link (the dllimport \ dllexport is related to zend_api macro)
Then I encountered the problem of reading and writing files. In fact, it is true. I manually copied the ciphertext of the written file to another file for testing. The result will be incorrect. if I copied the file directly, or directly operate on the original file.
Finally, I encountered an error where the memory cannot be read...
Finally, it is found that the file can be read in binary format due to the reading method of the file. if the file is read and written in text format, some special characters will be processed.
... Finally, we can test the function. However, if you really want to apply the function, we need to improve it. for example, when I encrypt it, I directly generate the encrypted file under the original directory, A better way is to package the original php file for convenient management.
Then I started to build the zf framework, and I forgot about it, and there were still many things that were useless at the beginning.

?

?

====================================

Original article address:

Http://blog.sina.com.cn/s/blog_4d06da1f0100pgmj.html

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.