• (2 Pages)
  • +
  • 1
  • 2

Introduction to : Creating a Php extension for windows Rate Topic: ****- 1 Votes

#1 aaron1178  Icon User is offline

  • Dovakiin, Dragonborn
  • member icon

Reputation: 169
  • View blog
  • Posts: 1,303
  • Joined: 22-October 08

Posted 20 August 2011 - 01:39 AM

Introduction to: Creating an extension for php in windows

Table of Contents


  • 1.0 - Introduction
  • 1.1 - Php and Zend
  • 1.2 - Requirements
  • 1.3 - Php 5.3.x Source Code
  • 2.0 - Creating a new project
  • 2.1 - Additional Directories
  • 2.2 - PreProcessor Directives
  • 2.3 - Additional Library Directories and Dependencies
  • 2.4 - Structure of our extension
  • 2.5 - Extension Breakdown
  • 2.6 - Complete extension source code
  • 3.0 - Building and using our extension
  • 4.0 - What's Next


1.0 Introduction

Extensions for Php are like an unknown force, not many people dare venture into the unknown mysteries of extensions for Php. Although people sometimes Write, Design and Deploy extensions, the main contributor for Php extensions are actually the Php developers themselves.

This tutorial is part 1 of an ongoing series published here and when I get around to it, it will also be available on my site Dark Rising Studios as a tutorial as per this tutorial and a PDF file.

As mentioned above, this tutorial is an Introduction / Part 1 to the 'Creating an extension for Php in windows' series. This series goes through different features and methods to develop and deploy an extension for Php on the Windows operating system.

On the 3rd August 2010 at 9:19 PM I wrote 'Creating a Php extension in C++'. Since my passion to Write and complete this series grew, I realised that the above tutorial is outdated and ill-explained, so I deem the above tutorial Out of Date and inconsistent for learning material.

Note: Php extensions for the Microsoft OS are stored in Dynamic Linked Libraries or .dll

1.1 Php and Zend


Note: If you are a Web Developer and you don't know what Php is, then please crawl out from under that rock you have been living under for millennia and wake up, for crying out loud


Php is a widely-used general-purpose scripting language that is especially suited for Web development and can be embedded into HTML. Php is the top-most leading online web development scripting language that is used by more than 69% of websites. More can be found on Php by visiting their website php.net Posted Image

Zend has a long history of support for the PHP open-source community. Each year, Zend contributes significant manpower and other resources to help nurture & encourage advancement of both the PHP language and the community. More can be read on that article found here at the Zend website Zend Engine Posted Image

1.2 Requirements


Note: These requirements are required to successfully complete this series. If you think that you can accomplish this series outside the following requirements, then please so.


In order to successfully follow and complete this series, there is a number of requirements before we can proceed.




As we do not want to get side tracked from the purpose of this series, I will show you the How-to for the Php source code and explain why we need it.

1.3 Php 5.3.x Source Code

Once you have installed Wamp Server, Visual Studio C++ epress 2010 and Win Rar you will need to extract the Php source code to "Wamp Install Directory/bin" where "Wamp Install Directory" is where Wamp Server installed to Generally "C:/Wamp". For reference, please view Fig1 and Fig2.

Posted Image
Fig1

Posted Image
Fig2

We need the source code of our current wamp version of php. This is how we compile our extension so that it uses the correct up-to-date methods/functions.

You will also need a copy of config.w32.h file that for some reason does not come with Php 5.3.x or above, I downloaded the Php 5.2.17 and extracted it via Win Rar to "C:\Wamp\bin\php-5.3.5\main". You can find the Php-5.2.17 available in Php's archives here for free download. Since you only need the one file, I have included a Win Rar file containing the config.w32.h file.

Attached File  config.w32.h.zip (2.12K)
Number of downloads: 1714

2.0 Creating a new project

We want to create a new project so we can begin on writing, developing and deploying our extension so it is available for Php. To do this, open up Visual Studio C++ express 2010 and create a new project. This is accomplished via "File -> New Project" or "New Project" on the start page.

Select Win32 Project and enter a name. For this chapter I am using "Introduction", please refer to Fig 3.

Posted Image

Fig 3

Click the "next" button and it will bring you to a new form with the title of "Win32 Application Wizard - Introduction Name of project. Now make sure under the heading "Application Type" that the DLL is selected and Empty Project under "Additional Options" is also selected, please refer to Fig 4.

Posted Image

Fig 4

We now have our project created and ready to configure to our needs.

Before we can continue on, we need at add a source file. To do this, either click on Source Files under your project and go Right Click -> Add -> New Item. Select C++ file (.cpp) and enter a name. For this extension I am adding the name return_string with a suffix of php_ so in total, "php_return_string". This is so the properties of the file are set to default and is able to be edited via properties Refer to 2.1. Refer to Fig 5

Posted Image

Fig 5

2.1 Additional Directories

We need to add some "Additional Directories" so that our IDE Visual Studio C++ can include and use methods / functions inside our Php extension. To do this we go to properties. To navigate to Properties, either Right click introduction Or what ever name you named the project -> Properties , or Project -> Properties, refer to Fig 6

Posted Image

Fig 6

Now navigate to C/C++ -> General -> Additional Include Directories. Now select the arrow to the right It's a dropdown box -> Edit Items. Now a screen titled Additional Include Directories will come up. To the far top right, there is a buttons panel, to the button to the left The file button, Click it, now add in the following directories, one by one Click the file icon for every directory given

C:\Wamp\bin\php-5.3.5\
C:\Wamp\bin\php-5.3.5\main
C:\Wamp\bin\php-5.3.5\TSRM
C:\Wamp\bin\php-5.3.5\win32
C:\Wamp\bin\php-5.3.5\Zend



It does not matter in which order you implement into the Additional Include Directories field, Refer to Fig 7

Posted Image

Fig 7

Okay, we have added the Additional Directories so that we may use methods / functions from Php and Zend.

2.2 PreProcessor Directives

PreProcessor Directives are just global variable for compilation time. The following directives will tell our build environment And Php and Zend that we want to configure our DLL with Php and Zend Windows 32-bit configuration. We also tell that the Zend debugger is set to off.

PHP_WIN32
ZEND_WIN32
ZTS=1
ZEND_DEBUG=0



To add the directives, please navigate to properties Refer 2.0, and click on C/C++ -> PreProcessor -> PreProcessor Directives and add Refer to 2.0 the above under Introduction_exports. Refer to Fig 8

Posted Image

Fig 8

These are all the PreProcessor Directives that we need for this chapter. So we now have:

  • New project named "Introduction"
  • 5 Additional Include Directories
  • 4 PreProcessor Directives


So in 2.3, we will add Additional Libraries and Dependencies to our Introduction extension.

2.3 Additional Library Directories and Dependencies

When creating an extension, be sure to remember to complete this step. This will reference our extension to the current Php version and functions that have already been built. This is to allow of extension to communicate with Php. Not following this step will mass errors.

Navigate to Properties -> Linker -> General -> Additional Library Directories and add the following to it. Please reference Fig 9 to do so.

C:\Wamp\bin\php\php5.3.5\dev\

Posted Image

Fig 9

The above directory has to be the current Php version that our extension uses with Wamp.

Now, to the dependencies. This will add the file that we need. It finds the file in the above directory and creates a dependency to it.

php5ts.lib Note that earlier versions of Php use php5.lib

Navigate to Properties -> Linker -> Input -> Additional Dependencies and add the following to it. Please reference Fig 10 to do so.

Posted Image

Fig 10

2.4 Structure of our extension

In this section of the tutorial, the full source code for our extension will be posted here and you will be given a complete line-by-line description on what happens and what it does.

Please note, that after trying a few different methods to return a string parameter, no luck was found. So our extension will return a pre-defined string depending on a boolean value (true / false)

#define PHP_COMPILER_ID  "VC6"

#include "php.h"


ZEND_FUNCTION(use_html);

zend_function_entry use_functions[] = 
{
	ZEND_FE(use_html, NULL)
	{NULL, NULL, NULL}
};

zend_module_entry use_html_module_entry = 
{
	STANDARD_MODULE_HEADER,
	"Use Html",
	use_functions,
	NULL, NULL, NULL, NULL, NULL,
	"1.0.0-tutorial",
	STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(use_html);

ZEND_FUNCTION(use_html)
{
	 bool useHtml;

	 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &useHtml) == FAILURE)
	 {
		 E_ERROR;
		 return;
	 }

	 if(useHtml)
	 {
		 php_printf("This string uses <a href='#'>Html</a>");
	 }
	 else
	 {
		 php_printf("This string does not Html");
	 }

	 return;
}




2.5 Extension Breakdown

Now that you have had a glance at the extension code, it doesn't really require a lot of code to write simple extensions. In this chapter, we will dissect our extension line-by-line. Lets get to it shall we.

#define PHP_COMPILER_ID  "VC6"



This line tells our extension to compile with Php with the defined PreProccessor directive (PHP_COMPILER_ID). When build time comes, this allows our extension to be 'silently' built with Visual C++ 6. What I mean by silent is, that it tricks Php in thinking that we are building our extension with Visual C++ 6, which we are not, we are building with a later version of Visual C++.


#include "php.h"



Well, it is as it seems. This line tells the compiler to scan all directories to look for the Php header file. Which can be found in C:\wamp\bin\php-5.3.5\main

ZEND_FUNCTION(long_return);



ZEND_FUNCTION(); declares a new C function that complies with Zend's internal API. This takes 1 known parameter which as of date, is the functions name, which will be named long_return

zend_function_entry use_functions[] =



Now that we have declared the functions to be exported, you also have to introduce them to Zend. Introducing the list of functions is done by using an array of zend_function_entry's. This array contains all functions that are to be made available externally, with the function's name as it should appear in Php.

ZEND_FE(use_html, NULL)
{NULL, NULL, NULL}



ZEND_FE(function_name, arg_types) defines a function entry of the name function_name in zend_function_entry. It requires a corresponding C function We declared it in the last line of code above. arg_types has to be set to NULL.

You can see that the last entry in the list always has to be {NULL, NULL, NULL}. This marker has to be set for Zend to know when the end of the list of exported functions is reached.

zend_module_entry use_html_module_entry =



This defines a zend module for our extension. We HAVE use our function name followed by _module_entry or this will throw errors at build. It contains all necessary information to describe the contents of this module to Zend.

    STANDARD_MODULE_HEADER,
    "Use Html",
    use_functions,
    NULL, NULL, NULL, NULL, NULL,
    "1.0.0-tutorial",
    STANDARD_MODULE_PROPERTIES



STANDARD_MODULE_HEADER contains four bits of important information, instead of filling out the four bits, we use STANDARD_MODULE_HEADER. This will fill out the four bits of information that we need More on this in another chapter so we do not need to do so.

"Use Html" is the name of the module. It is a string value that will also show up in the phpinfo() table More on this later. This value is required.

use_functions is array of functions we defined beforehand. We use the exact name of the defined structure in order for zend to do its magic. This is a must have parameter.

NULL, NULL, NULL, NULL, NULL These are parameters that we do not need, so we set them as unused, NULL. More on this in a later chapter.

1.0.0-tutorial This is the version of the module / function NOT the extension. You can use NO_VERSION_YET if you don't want to give a version yet, but it is really recommend that you add a version string here.

STANDARD_MODULE_PROPERTIES This is all parameters of the remaining module. We use STANDARD_MODULE_PROPERTIES because it is recommended to do so, unless we use startup / shutdown functions, which we do not.

ZEND_GET_MODULE(use_html);



ZEND_GET_MODULE()'s purpose is to pass the module information back to Zend in order to inform the engine about the module contents. This is a required line, or zend will throw yet another error.

ZEND_FUNCTION(use_html)



Implementing the exported functions is the final step

The function declaration is done using ZEND_FUNCTION. After the declaration, code for checking and retrieving the function's arguments, argument conversion, and return value follows.

bool useHtml;



If you do not understand this line, it's ok, all this will do is create a boolean true / false variable named useHtml. This is so we can store the parameter value of our function inside our useHtml variable.

 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &useHtml) == FAILURE)



I'm not going to go into detail with the if statement, you should already know what it is and how to use it.

zend_parse_paramerters() The first argument to this function is supposed to be the number of parameters passed to your function, so ZEND_NUM_ARGS() can be used for that. The second parameter should always be the TSRMLS_CC macro.

The third argument is a string that specifies the number and types of arguments your function is expecting. We use |b, where | = optional and b = boolean value. So |b means an optional boolean parameter.

The final argument(s) are pointers to variable to store parameter data in, in this case, we store a boolean value in our useHtml variable.

FAILURE This calls the FAILURE macro that is determines the success of failure of the if statement. So if we do not receive anything buy optional boolean, it will return FAILURE or true in other senses.

E_ERROR;
return;



E_ERROR This will throw an E_ERROR message to Php if the enclosing if statement is true.

return If the enclosing if statement is true, it will return it from our function so we cannot display any more data. This is useful if we want to print a string and have it exit our function.

php_printf("This string uses <a href='#'>Html</a>");



if the enclosing if statement is true If our useHtml variable is true, then this will call a php function that will print a pre-defined string.

2.6 Complete extension source code


Additional Directories
C:\Wamp\bin\php-5.3.5\
C:\Wamp\bin\php-5.3.5\main
C:\Wamp\bin\php-5.3.5\Zend
C:\Wamp\bin\php-5.3.5\Win32
C:\Wamp\bin\php-5.3.5\TSRM



PreProcessor Directives
PHP_WIN32
ZEND_WIN32
ZTS=1
ZEND_DEBUG=0



Additional Library Directories
C:\Wamp\bin\php\php5.3.5\dev\



Additional Dependencies
php5ts.lib
OR
php5.lib



Extension Source Code
#define PHP_COMPILER_ID  "VC6"

#include "php.h"


ZEND_FUNCTION(use_html);

zend_function_entry use_functions[] = 
{
	ZEND_FE(use_html, NULL)
	{NULL, NULL, NULL}
};

zend_module_entry use_html_module_entry = 
{
	STANDARD_MODULE_HEADER,
	"Use Html",
	use_functions,
	NULL, NULL, NULL, NULL, NULL,
	"1.0.0-tutorial",
	STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(use_html);

ZEND_FUNCTION(use_html)
{
	 bool useHtml;

	 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &useHtml) == FAILURE)
	 {
		 E_ERROR;
		 return;
	 }

	 if(useHtml)
	 {
		 php_printf("This string uses <a href='#'>Html</a>");
	 }
	 else
	 {
		 php_printf("This string does not Html");
	 }

	 return;
}



3.0 Building and using our extension

Now that we have our extension written, it is now time for us to build it and use it in Php. Lets begin the final process of this chapter by building our project. This is accomplished via Debug -> Build Solution or the F7 key. Your project is now built, if not, start this tutorial again. Refer to Fig 11 for more information.

Posted Image

Fig 10

Now that our extension has been built into a Dynamic Extension (.dll), open the wamp tray manager and stop ALL services. Refer to Fig 11

Posted Image

Fig 11

Once all Wamp services have stopped, navigate to the debug folder of your extension. Find where it says Introduction.dll The name of our extension.If you cannot find it, the console in Visual Studio C++ express will have the direct path to our extension.

Once you have found our extension, copy it and navigate to C:\Wamp\bin\php\php5.3.5\ext where this is the directory of Wamps current running Php version. Paste the extension into the file containing the rest of the extensions.

Now we need to edit php.ini. To do so, we need to go to Wamp Manager -> PHP -> php.ini and click it. This should bring it up in notepad.exe for default. Scroll down just over half way to the Dynamic Extensions section, of hit Ctrl F and enter extension= and add the following line to the end of the list.

extension=Introduction.dll



Where Introduction.dll is the name of our project built in Visual Studio. Now start ALL of Wamp's services. This should start strait away. If you get errors, review the Apache log.

Now that our extension is loaded in Php, it's time to check that Php is actually using our extension. If not, redo the whole tutorial.

Create a Php page inside Wamp's WWW directory and add the following to it.

<?php
phpinfo();
?>


Load the page in a web browser http://localhost/test.php for me and scour the entire page looking for our extension name Use Html. If it is there, Php is using it :) Refer to Fig 12.

Posted Image

Fig 12

Because we named it Use Html it will generally be more towards the bottom as all extensions are sorted in alphabetical order.

Now on the same Php page, replace the text with

<?php

use_html(true);

?>



We should now see "This string uses Html". If we set the parameter to false or do not parse a parameter will see "This string does not Html"

It's alive

4.0 What's Next

Well, now that's over, you are probably wondering what's next right? Well for those hoping for more tutorials on this rare topic, there will be more forthcoming tutorials. Once the series is finished, you will be able to write your own extensions that could be the next big thing for Php :) Well hopefully anyway.

I have had a lot of fun writing this tutorial and hope you join me for the series,

Thanks,

Aaron Thompson

Is This A Good Question/Topic? 4
  • +

Replies To: Introduction to : Creating a Php extension for windows

#2 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3730
  • View blog
  • Posts: 6,017
  • Joined: 08-June 10

Posted 07 November 2011 - 04:45 PM

Hey.

Great tutorial! :)


For people using VC9 builds of Apache and PHP, you will get errors when compiling the extension code in the tutorial. To fix it, try these two steps:

  • Instead of copying the config.w32.h file from a 5.2 version of the code, or using the one aaron1178 provides, copy the win32\build\config.w32.h.in file from the 5.3 source and save it as main\config.w32.h.

  • Change the PHP_COMPILER_ID definition in the extension source code to read "VC9" instead of "VC6".

Was This Post Helpful? 2
  • +
  • -

#3 aaron1178  Icon User is offline

  • Dovakiin, Dragonborn
  • member icon

Reputation: 169
  • View blog
  • Posts: 1,303
  • Joined: 22-October 08

Posted 07 November 2011 - 07:19 PM

Sorry about these errors guys. I wasn't aware of them as I must be using an older version of their source code. Atli has provided an adequact way of solving the issues.

Thanks for the feedback Atli
Was This Post Helpful? 0
  • +
  • -

#4 codeprada  Icon User is offline

  • Changed Man With Different Priorities
  • member icon

Reputation: 948
  • View blog
  • Posts: 2,357
  • Joined: 15-February 11

Posted 14 November 2011 - 04:10 PM

Nice tutorial. Definitely going to try this out.
Was This Post Helpful? 0
  • +
  • -

#5 yunter  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 25-December 11

Posted 25 December 2011 - 08:06 PM

oh, Great tutorial!

Why image file can't see
Was This Post Helpful? 0
  • +
  • -

#6 abxccd  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 05-January 05

Posted 10 April 2012 - 04:35 AM

Is there anyway to get the extension to compile as non-threadsafe?
Was This Post Helpful? 0
  • +
  • -

#7 olibenu  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 45
  • View blog
  • Posts: 538
  • Joined: 31-December 08

Posted 10 April 2012 - 06:23 AM

nice!
it's even a tutorial on how to present a tutorial!
Was This Post Helpful? 1
  • +
  • -

#8 aaron1178  Icon User is offline

  • Dovakiin, Dragonborn
  • member icon

Reputation: 169
  • View blog
  • Posts: 1,303
  • Joined: 22-October 08

Posted 11 April 2012 - 01:36 AM

View Postabxccd, on 10 April 2012 - 10:35 PM, said:

Is there anyway to get the extension to compile as non-threadsafe?


To be honest abxccd, I am not 100% entirely sure. I am leaning towards no.

View Postolibenu, on 11 April 2012 - 12:23 AM, said:

nice!
it's even a tutorial on how to present a tutorial!


Why thank you :)
Was This Post Helpful? 0
  • +
  • -

#9 bahman2216  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 18-January 08

Posted 09 December 2012 - 06:50 AM

thanks for good article

I just have an error during compile via php 5.2.9 but it is work good on php 5.3.x

here is my error in php 5.2.9
c:\program files\microsoft visual studio 9.0\vc\include\sys\stat.inl(44) : error C2466: cannot allocate an array of constant size 0
Was This Post Helpful? 0
  • +
  • -

#10 nobelb  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 13-December 12

Posted 13 December 2012 - 06:53 PM

Thanks, Great tutorial!

If some one get error likes “error LNK2019: unresolved external symbol”? may mean that you are compiling a x64 library in a Win32 project.

How to compile a 64-bit application using Visual C++ 2010 Express
http://stackoverflow...-c-2010-express

I holp this can help some people.
Was This Post Helpful? 0
  • +
  • -

#11 karimkhan_it  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 07-January 11

Posted 19 June 2013 - 08:32 AM

My project build successfully and I copied dll fine in approprite folder.

Even it is giving function not defined error and in case of phpinfo(); nothing about use_html!
Was This Post Helpful? 0
  • +
  • -

#12 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3730
  • View blog
  • Posts: 6,017
  • Joined: 08-June 10

Posted 20 June 2013 - 11:38 PM

karimkhan_it, we need more details than that. It's pretty much impossible to know what's wrong without knowing exactly what's going on.
Was This Post Helpful? 0
  • +
  • -

#13 aaron1178  Icon User is offline

  • Dovakiin, Dragonborn
  • member icon

Reputation: 169
  • View blog
  • Posts: 1,303
  • Joined: 22-October 08

Posted 04 July 2013 - 06:57 PM

View Postkarimkhan_it, on 20 June 2013 - 02:32 AM, said:

My project build successfully and I copied dll fine in approprite folder.

Even it is giving function not defined error and in case of phpinfo(); nothing about use_html!


View Postkarimkhan_it, on 20 June 2013 - 02:32 AM, said:

Fatal error: Call to undefined function tutorial() in D:\wamp\www\test.php on line

My project build successfully and I copied dll fine in approprite folder.

Even it is giving function not defined error and in case of phpinfo(); nothing about tutorial!


karimkhan, notice that the line in bold uses a function tutorial, please do not use any material from:

It's old and a bad tutorial I wrote.

As Atli explained, we need more details. Are you in windows? or linux?. Are you enabling the extension from the .ini? We need to know what steps you took, after you compiled the .dll file... and we need to know where you placed it.

This post has been edited by aaron1178: 04 July 2013 - 06:58 PM

Was This Post Helpful? 0
  • +
  • -

#14 alebonfa  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 15-September 13

Posted 15 September 2013 - 04:43 AM

Hi, Aaron,

Thanks for your article. It's a fantastic and detailed article.
I've tested it and It's worked perfectly.

I have one only doubt:

I've downloaded the php_dbase source code in php.net.
How can I join this source code in this project?

I need to compile que php_dbase.dll to last php version (5.5.3).

Thanks,
Alexandre Bonfa
Was This Post Helpful? 0
  • +
  • -

#15 StephenIsienyi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 10-November 08

Posted 12 October 2013 - 06:02 PM

Hi Aaron,

This is an awesome article.

There are a couple questions though - hopefully they are minor.

1) What should I do to get around a requirement issue? My PHP version is 5.3.10 instead of the 5.3.5 you used. I also do not have the main, TSRM, Win32 or Zend directories in my C:\Wamp\bin\php\php-5.3.10 folder

2) What other modifications would I need to make to successfully port this extension from Windows to a Linux successfully?

Thanks,
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2