LinuxGuruz
Toll Free Numbers
Custom Search
MAIN MENU
Main Page
IT Jobs
IPTABLES
Linux Forum
HTML Forum
PHP Forum
MySQL Forum
Linux FAQ
Linux Articles
About Us
Privacy Policy

ADD TO FAVORITES


MARC

Mailing list ARChives
- Search by -
 Subjects
 Authors
 Bodies





FOLDOC

Computing Dictionary






Cheap UK Web Hosting Provider

Cheap Dedicated Servers UK

Cheap Linux VPS Hosting UK

Cheap Cloud Hosting UK



Icons
Icons


free brochure template
Free Brochure Template

Web Hosting

Domain Names

Web Design

Reseller Hosting

Registro de Dominios

Reseller Hosting


Toll Free Number for $2.00/Month!!!

Toll Free Number for $2.00/Month!!!
The PHP3 Dynamic Loadable Module HOWTO

The PHP3 Dynamic Loadable Module HOWTO
Mathieu Kooiman <caps@gge.nl>
v0.02, 13 Dec 1999


This is the PHP3 Dynamic Loadable Module HOWTO, explaining how
to setup PHP to use Dynamic Loadable Modules (DLM) and write your own 
PHP extension. In this HOWTO Dynamic Loadable Modules are referred to
as DLM.


Table of Contents


1.	General Information.

	1.1 What is PHP?
	1.2 What are Dynamic Loadable Modules?
	1.3 About the Author.
	1.4 Copyright.
	1.5 Contributors.


2.	Compiling PHP for use with DLM.

	2.1 Getting PHP.
	2.2 Compile PHP a CGI binary.
	2.3 Compile PHP as an Apache Module (mod_php3).


3.	Writing your own Module.

	3.1 Basic setup.
	3.2 First example (Hello_World).
	3.3 Returning Values.
	3.3.1 LONG.
	3.3.2 STRINGS.
	3.3.3 FLOATING POINT or DOUBLES.
	3.3.4 ARRAYS.
	3.3.5 OBJECTS.
	3.3.6 MyModule.c.
	3.4 Creating Variables.



1. General Information.


1.1 What is PHP?
	
 	PHP (Hypertext Preprocessor) is a HTML Preprocessor. Enabling
	you to create dynamic webpages. If you want more information,
	you will find it at http://www.php.net.


1.2 What are Dynamic Loadable Modules?

	A Dynamic Loadable Module (DLM) are libraries with functions,
	which PHP can load to extends it functionality.


1.3 About the Author.

	Mathieu 'CaPS' Kooiman from The Netherlands.
	Born in 1983 and has been coding in PHP since March 1999.
	
	I can be found on #PHP on EfNet from time to time, or #NL on IRCnet 
	more regularly. If you need to know more, email me at caps@gge.nl


1.4 Copyright.

        This PHP Dynamic Loadable Module HOWTO(c) 1999 Mathieu Kooiman
	may be reproduced in any possible way as long as the author is
	notified.


1.5 Contributors.

        While writing this HOWTO I received help from some people.
        At this moment I just wanna thank Aztech_ helping me proof
	read and make adjusts. As did Randall Goguen (aka Ranman) who
	wrote the part about compiling Apache for use with
	DLM and made some stuff make sense :))

	Thanks guys!

2. Compiling PHP for use with DLM.


2.1 Getting PHP.

	You can download the PHP source free from:
	http://www.php.net/distributions/php-3.0.12.tar.gz

* THE SOURCE FILES SHOWN HERE WILL NOT!! WORK!!! WITH PHP4 *
* THIS IS BECAUSE PHP4 HAS A REDONE THE BASE ENGINE (ZEND) *


2.2 Compile PHP a CGI binary.


tar -xvzf php-3.0.12.tar.gz             # Extract the tarball.
cd php-3.0.12			
./configure                             # Configure PHP.
-------------------- HOLD IT ------------------

Here we gotta change the Makefile, fire up your editor
and look for "LDFLAGS" in the Makefile.
You'll have to append -rdynamic to it.

Change the line:
LDFLAGS =  $(LDFLAGS_SHLIB) $(LDFLAGS_SHLIB_EXPORT)
To:
LDFLAGS =  $(LDFLAGS_SHLIB) $(LDFLAGS_SHLIB_EXPORT) -rdynamic

-------------------- CONTINUE ---------------------
make					# Compile PHP.
make install				# Install.
	

2.3 Compile PHP as an Apache Module (mod_php3).

tar -xvzf php-3.0.12.tar.gz             # Extract the tarball.
cd php-3.0.12
./configure \                          	# Configure PHP.
 --with-apxs=/usr/local/apache/bin/apxs 	
make					# Compile PHP.
make install				# Install.


3. Writing your own Module.


3.1 Basic setup.

	To start writing your own PHP module, I advice you to make a
	little subdirectory somewhere ie:  MyModule.
		
cd ~					# Go to your Home Directory.
mkdir MyModule				# Make the directory.
mkdir MyModule/SRC			# I prefer using a SRC dir,
					# so lets make that one too.
cd MyModule				# Change to the MyModule
					# directory.
cp /path/to/php-3.0.12/dl/phpdl.h .	# Copy phpdl.h to our directory.
		
			
	Now, lets create a Makefile in MyModule/ to ease compiling.
	I'm using the MyModule.c file as an example.
	MyModule.c is describled further below.

	* NOTE *
		This Makefile works on my machine, which runs
		Redhat 5.2 - Linux 2.0.36 - GCC version 2.7.2.3
		and also on
		Slackware 4.0 - Linux 2.2.12 -GCC version 2.7.2.3	

		It MIGHT, MIGHT NOT work on your machine.

# WHEN USING A CGI BINARY

# Create a file called  ~/MyModule/Makefile that contains the following:
# Note: The use of Tabs are very important.

CC = cc -O2 -Dbool=char -DHAS_BOOL \
 -I/usr/local/include \
 -I/YourPHPsourceDirectory/ -fpic

LD = cc -shared -L/usr/local/lib -rdynamic

all:	MyModule.so

HELLO_OBJS = SRC/MyModule.o
MyModule.so:	$(HELLO_OBJS)
	$(LD) -o $@ $(HELLO_OBJS)
SRC/MyModule.o: SRC/MyModule.c
	$(CC) $(CFLAGS) -DCOMPILE_DL=1 -c -o $@ $<

	
3.2 First example (Hello_World).

	To get you started here's a example with explanations.
	I'll creating a PHP function called Hello_World. Place this file
	in MyModule/SRC/

cd SRC/				# Change to the SRC directory.

-------------------- MyModule.c --------------------

# Create the file ~/MyModule/SRC/MyModule.c containing the following:
	

#include "../phpdl.h"
	
/* Define the functions that will be accessible to PHP */
	
DLEXPORT void hello_world (INTERNAL_FUNCTION_PARAMETERS);
	
/* prototype for function_entry	is :
 * {"PHP_FUNCTION", Your_C_Function, 1} 
 */

function_entry MyModule_functions[] = {
       	{"hello_world", hello_world, NULL},
       	{NULL, NULL, NULL}
};

/*
 * Register your functions within PHP
 */
	
php3_module_entry MyModule_module_entry = {
 "MyModule", MyModule_functions,
 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL
};

#if COMPILE_DL
DLEXPORT php3_module_entry *get_module(void) { 
	return &MyModule_module_entry; 
}
#endif

/* Alright! PHP now "knows" Hello_World exists. 
 * Now lets write the actual function
 */
	
DLEXPORT void hello_world (INTERNAL_FUNCTION_PARAMETERS) {
	// Well, its ugly, but easy :)
	char MyFunction[15];
	sprintf(MyFunction, "Hello World!");
		
/* Create the return value.
 *  We gotta alloc memory for the string,
 *  for this we use estrdup()
 */

	return_value->value.str.val = estrdup(MyFunction);
	return_value->value.str.len = strlen(MyFunction);
	return_value->type = IS_STRING;
}

/* And Voila! Our function is complete!!! */
	 

cd ../		# Change back to the ~/MyModule directory.

Alright!! Compiling time!
In ~/MyModule/ do a 'make' and you'll see something like this:

# make
cc -shared -L/usr/local/lib -rdynamic -o MyModule.so SRC/MyModule.o

By now you should have 'MyModule.so' in MyModule/
This is the library PHP can load to extend its functions! 
All you need now is a php file to test it with.

test.php3:
	<?
		dl("/path/to/MyModule.so");
		$MyVar = hello_world();
		echo $MyVar;
	?>

The function dl() loads the library and "adds the functions to PHP". 
After loading the library, I assigned the return value of hello_world() to
$MyVar. In theory, $MyVar now gets the value of the C variable MyFunction.

Well, we're all set to test it now!

# php test.php3
  Content-type: text/html

  Hello World!

Well, whadda ya know. It worked!

# If you compiled PHP as an Apache Module just point your browser at
# http://localhost/test.php3

3.3 	Returning Values.
	
	The reason why I talk about RETURNING variables first is,
	this probably'll be what you'll use most.

	Creating variables in C functions accessible in PHP
	just doesn't make to much sense to me.

	There are several ways of returning values, especially
	several TYPES. There are LONGS, ARRAYS, DOUBLES, STRINGS etc.
	The following section handles just that. There are several
	macro's defined, which you can use to ease up returning values.

		* RETURN_LONG(LongValue);
		* RETURN_DOUBLE(DoubleValue);
		* RETURN_STRING(String, 1);
		* RETURN_STRINGL(String, Length, 1);
		* RETURN_TRUE;
		* RETURN_FALSE;


3.3.1   LONG.

	If you wish to return a "LONG",	you'll have to change your
	return values;
	
	long MyVar = 100;
	
	return_value->value.lval = MyVar;
        return_value->type = IS_LONG;
	
	Notice the 'value.lval'. LVAL stands for Long Value;

	Say your function in PHP would be called: Return_100();
	$Hundred = Return_100; would make $Hundred 100 :) 

	The easy way: RETURN_LONG(MyVar);


3.3.2   STRINGS.
	
	We've learned how to return a string in MyModule.c
	But I'll paste the code again for simple reference.

	char MyFunction[15];
        sprintf(MyFunction, "Hello World!");

	return_value->value.str.val = estrdup(MyFunction);
        return_value->value.str.len = strlen(MyFunction);
        return_value->type = IS_STRING;

	The easy way: RETURN_STRING(MyFunction, 1);
	

3.3.3   FLOATING POINT or DOUBLES.

	Say you want to calculate VAT, which is 17.5% in The Netherlands,
	you can't use a LONG. You'll have to use a FLOAT or DOUBLE in C,
	and a DOUBLE in PHP.

	double Calculated_VAT;
	int Value=100;
	double VAT=17.5;

	Calculated_VAT=((Value/100) * VAT) + Value;
	
	return_value->value.dval = Calculated_VAT;
	return_value->type = IS_DOUBLE;
	
	The easy way: RETURN_DOUBLE(Calculated_VAT);


3.3.4	ARRAYS.
	
	Returning an array is a bit different from returning an other type.
	First of all you got two types of arrays. 
		* Associative arrays......... $foo["bar"]	
		* Enumerated arrays.......... $foo[0]
	
	They both need different handling.
	First of all you'll have to initialize the array. Usually
	you would do this with a 'pval *MyArray' but since we are RETURNING
	an array. We will init 'return_value' as an array.
	
	int i;
        if (array_init(return_value) == FAILURE) {
		php3_error(E_ERROR, "Error initializing Array");
		return;
	}

        for (i=0;i<10;i++) {
                add_next_index_long(return_value,i);
        }
	
	This would return an array:
		array[0] = 0 ... array[10] = 10;
	
	Of course you can return an array with other values:
		(as taken from /php3.0.12/apidoc.txt)

		add_index_long(return_value, index, MyLongValue)
		add_index_double(return_value, index, MyDoubleValue)
		add_index_string(return_value, index, MyString)
		add_index_stringl(return_value, index, MyString, length)

		These functions will add a specific variable on
		place 'INDEX'. 

			
       Returning an associative array is again different from returning
       any other TYPE. Again you will have to initialize the return
       array.

                array_init(return_value);

       You might want to add some error handling here, else, if something
       goes your module will cause an 'Segmentation Fault'.

if (array_init(return_value) == FAILURE) {
       	php3_error(E_ERROR, "Couldn't initialize array Return_Value!");
        return;
}

        After this you might want to add an element:

                long MyLongValue=100;
                add_assoc_long(return_value, "foobar", MyLongValue);

 	All functions for adding elements to an associative array:
		(as taken from php-3.0.12/apidoc.txt)

   	add_assoc_long(return_value,Key,LongValue)
	add_assoc_double(return_value,Key,DoubleValue)
   	add_assoc_string(return_value,key,String)
   	add_assoc_stringl(return_value,key,String,length) 

	Futheron I'll show an example of returning arrays.


3.3.5 	OBJECTS.

	An object is (as Rasmus said one day in #php) an encapsulation
	of methods and variables. Well, I couldn't agree more :D
	Well, we can return these. You can even register a function
	on return_value. So you can return a complete class!

	First you will have to initialize an Object, this is much like
	initializing an array. Simply call object_init();

		if (object_init(return_value) == FAILURE) {
			php3_error(E_ERROR,"Couldn't init an Object!");
			return;
		}

	Returning a object property is much like returning a regular
	variable.

	add_property_long(return_value, "MyWealth", 0);
	add_property_double(return_value,property_name,Double)
	add_property_string(return_value,property_name,String) 
	add_property_stringl(return_value,property_name,String,length)

	Adding a function to your return class is also very easy to do.
	First write the method you want to add to your class, I will
	show you a simplistic method.

-------------------- MyModule.c --------------------

#include "../phpdl.h
	
DLEXPORT void My_Returned_Class (INTERNAL_FUNCTION_PARAMETERS);

// The functions accessible for PHP
function_entry MyModule_functions[] = {
	{"MyClass", My_Returned_Class, NULL},
	{NULL, NULL, NULL}
};

php3_module_entry MyModule_module_entry = {
 "MyModule", MyModule_functions,
 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL
	};

#if COMPILE_DL
DLEXPORT php3_module_entry *get_module(void) {
return &MyModule_module_entry;
}
#endif

void MyMethod (INTERNAL_FUNCTION_PARAMETERS) {
	/*
	 * This functions takes 2 arguments, substracts them,
	 * and returns them.. well if THIS aint easy.. WHAT is:)
	 */

	pval *Number1, *Number2;

	if (ARG_COUNT(ht) != 2 || 
		getParameters(ht,2,&Number1,&Number2)==FAILURE) {
       			WRONG_PARAM_COUNT;
	}
// Make sure we can use ex. 17.5
	convert_to_double(Number1);
	convert_to_double(Number2);
	
// Return the substracted value (the easy way)
	RETURN_DOUBLE(Number1->value.dval - Number2->value.dval);
}

// Now.. Add it to your function which returns an Object.
	
DLEXPORT void My_Returned_Class(INTERNAL_FUNCTION_PARAMETERS) {
	// Create an Object
	object_init(return_value); 

	// Register the Method
	add_method(return_value, "minus", MyMethod); 
}


You might want to create MyModule2/
cd ~				# Go to your home directory.
mkdir MyModule2
mkdir MyModule2/SRC
cp MyModule/Makefile MyModule2/Makefile
cp MyModule/phpdl.h MyModule2/phpdl.h

Then save the above file (MyModule.c) as MyModule2/SRC/MyModule.c
Type 'cd MyModule2' and do a 'make'.

Now make a test.php3 again :))

test.php3
	dl("/path/to/MyModule.so");
	$MyMathClass = MyClass();
	echo $MyMathClass->minus(10,5);

When running test.php3, you would see something like:
	# php test.php3
	Content-type: text/html
	
	5

And again, it works :))

# If you compiled PHP as an Apache Module just point your browser at
# http://localhost/test.php3

3.4 Creating Variables.

	For some strange reason you might want to make variables from
	within a function. The only thing I can think of would be making
	some global variables accessible with some "statistic" values;
	for example with phpIrc, how many users there are on a channel.
	
	Lets create a var called $NUMBER_OF_USERS, and say it would be
	called with phpIrc_Join_Channel(); This is hypothetical. I
	don't know wether phpIrc has this function. Creating variables
	in the symbol table is very easy, there are three macro's available
	to help you do so.

		     * SET_VAR_STRING(name,value)
				Be careful with this one! You'll have 
				to allocate memory for it before you
				call the macro.

		     * SET_VAR_DOUBLE(name,value)
       		     * SET_VAR_LONG(name,value)

	You can get the real phpIrc on http://www.phpwizard.net/
	
	By now you MIGHT come across a little typo in php.h.
	The macro which defines looks like this:

#define SET_VAR_DOUBLE(n,v) { \
	{ \
	pval var; \
	var.value.dval = (666.6); \
	var.type = IS_DOUBLE; \
_php3_hash_update(&GLOBAL(symbol_table)),
// Looky here, an extra ')'!!
                                         
	(n), \
	strlen((n))+1, \
	&var, \
	sizeof(pval),NULL); \
        } \
        }

	You can simply remove the ')' and recompile or just use this macro
	used in the example below.

 	
#include "phpdl.h"

#define SET_MYVAR_DOUBLE(n,v) { \
                   { \
                   pval var; \
                   var.value.dval = (v); \
                   var.type = IS_DOUBLE; \
                   _php3_hash_update(&GLOBAL(symbol_table), \
                                     (n), \
                                     strlen((n))+1, \
                                     &var, \
                                     sizeof(pval),NULL); \
                   } \
}
	
DLEXPORT void phpIrc_Join_Channel(INTERNAL_FUNCTION_PARAMETERS);
	
function_entry MyModule_functions[] = {
               {"join_channel", phpIrc_Join_Channel, NULL},
               {NULL, NULL, NULL}
};

php3_module_entry phpIrc_module_entry = {
 "phpIrc", MyModule_functions,
 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL
	};


#if COMPILE_DL
DLEXPORT php3_module_entry *get_module(void) {
return &phpIrc_module_entry; }
#endif

DLEXPORT void phpIrc_Join_Channel(INTERNAL_FUNCTION_PARAMETERS) {
	/*
	 * Imagine about some code sending JOIN #PHP\n\r
	 * through a socket around here:))
	 */

if (_php3_hash_exists(active_symbol_table,"NUMBER_OF_USERS",
 sizeof("NUMBER_OF_USERS")))  {
	php3_error(E_WARNING, "NUMBER_OF_USERS already exists");
} else { 
	SET_MYVAR_DOUBLE("NUMBER_OF_USERS", 666.666);
	}
}



Congrats!!! You should now should be able to write your own PHP Modules!

Good luck!


Mathieu 'CaPS' Kooiman
caps@gge.nl

        Anyone who wishes to make additions or changes to this
PHP Tip email them to caps@gge.nl

Return to the LinuxGuruz PHP Tutorials Page
Return to the LinuxGuruz Main Page


www.PHP.net Search Engine


Restrict the search to:
Copyright © 1999, 2000 The PHP Development Team.
Submit a PHP Tutorial

Title:

Contributor:

IRC NICK: (optional)

E-Mail Address: (optional)

Tutorial:

Return to the LinuxGuruz PHP Tutorials Page
Return to the LinuxGuruz Main Page

RESOURCE LINKS
Linux
Apache
HTML
PHP
MySQL
PostgreSQL
Oracle
CGI
Perl
Java
C/C++
Bash
Tcl
Networking
Security
ISP
IRC
Xwindow
Laptop
Graphics
Hardware
Reference
Misc

Broadband


filing cabinet

  • Buy Batteries for Laptops and Cameras
  • Notebooks
  • Michael Fertik
  • Reputation Defender

  • XP Style Icons
    XP Style Icons


    Network Certification


    Network Security


    Wireless Networking


    Canadian
    Web Hosting in Canada


    Drummer Portal


    Mending Media

    The Path Of
    Most Resistance


    Toll Free Number for $2.00/Month!!!

    Toll Free Number for $2.00/Month!!!


    Linux

    The Distributions





    Linux

    The Software





    Linux

    The News




    webmaster@linuxguruz.com
    Copyright © 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 and 2009 by LinuxGuruz