Possible to make an independent shared object of PHP?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
RazorCut
Forum Newbie
Posts: 2
Joined: Fri Jun 17, 2005 5:14 pm

Possible to make an independent shared object of PHP?

Post by RazorCut »

Howdy,

I'm new to the forums and I've got a question. I've been doing some research including drudging through PHP, Apache, and apr source code to try to figure out the answer; I'll continue to do this but I figure that maybe some experienced folks have some ideas.

My desire is to load up a PHP shared object into my server project so that the server can execute PHP code like Apache does. I can build PHP with a shared object for the Apache webserver...easy, piece of cake. When I load in this shared object in my own project manually, I get this error message from the dlerror() function of the dlfcn.h stuff:

undefined symbol: ap_loaded_modules

The ap_loaded_modules stuff seems to be a pretty deep aspect of the libraries that are a part of the Apache project. I suspect that given enough time, I can probably include all of the necessary Apache source code into my own project to get this stuff working, but I'd rather not do that.

I noticed that in the PHP source directory structure that this Apache shared object interface is used in $PHP/sapi/apache2handler, specifically php_functions.c. And there isn't much of this code, so this leads me to believe that it might be possible to build a more generic PHP shared object file that I can use, avoiding the need to make use of Apache's module loading stuff.

So my question(s) is/are: Is it possible to build a generic (non-Apache dependent) shared object of PHP? If not, how might I approach the problem of making this possible?

Many thanks!

-Ray
RazorCut
Forum Newbie
Posts: 2
Joined: Fri Jun 17, 2005 5:14 pm

Post by RazorCut »

Hello,

Turns out that I figured out the answer to my question, although I now have more. I built PHP like so:

Code: Select all

./configure --with-mysql --enable-embed
make
and it created a libphp4.so in the .lib directory. I copied this to a convenient place. I can successfully load this shared object (with dlopen()) and get the address (and set up the prototype) for the 'php_embed_init()' function defined in php_embed.h. Now, I don't know what to do from here.

The prototype for php_embed_init() is like so:

Code: Select all

int php_embed_init(int argc, char **argv PTSRMLS_DC);
In my case, PTSRMLS_DC is NULL. So, when I call php_embed_init, I just pass the argc and argv values passed in from my main(). When I run my program, I passed in the name of a file that has PHP code in it like so:

Code: Select all

%> ./test_so hello.php
My hello.php function has this code in it:

Code: Select all

<?php
$fh = fopen(&quote;log.out&quote;, &quote;w&quote;);
print &quote;Hello world!  (from hello.php)\n&quote;;
fwrite($fh, &quote;Hello world! (from hello.php)\n&quote;);
flose($fh);
?>
I was hoping that I'd miraculously see at least a 'hello world' pop out on my terminal, but I'm not that lucky.

Has anybody had any experience with using the php_embed stuff? What else should I be setting up and doing in order to get some PHP code to execute, now that I got the shared object loading working?

Thanks!
-Ray

P.S. Here is my source code so far:

so.h

Code: Select all

#ifndef SO_H
#define SO_H

#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>
#include <string.h>

//typedef void(*Misc)(char * buffer); // temporary test
typedef void(*Init)(int, char **);

struct module
{
	void *so; // shared object handle
	Init init;
};

typedef struct module module;

// function for checking libdl errors
int dlok(const char *msg);

// loads module into the struct module
void* loadmodule(module *mod, const char *soname);

// unloads the module
int unloadmodule(module *mod);

#endif
so.cpp

Code: Select all

#include &quote;so.h&quote;

// function for checking libdl errors
int dlok(const char *msg)
{
	char *err;
	int unsigned ret = 1;
	if ( (err = dlerror()) )
	{
		printf(&quote;%s: %s\n&quote;, msg, err);
		ret = 0;
	}
	return ret;
}

// loads module into the struct module
void* loadmodule(module *mod, const char *soname)
{
	printf(&quote;Loading %s ...\n&quote;, soname);

	// load the library, resolve symbols as they are needed
	mod->so = dlopen(soname, RTLD_LAZY);

	if ( mod->so )
	{
		// get the initialization functions address
		mod->init = (Init)dlsym(mod->so, &quote;php_embed_init&quote;);
		if ( !dlok(&quote;\\-php_embed_init() not found&quote;)) return 0;
	}
	else
		printf(&quote;dlopen failure: %s\n&quote;, dlerror());

	return mod->so;
}

// unloads the module
int unloadmodule(module *mod)
{
	return dlclose(mod->so);
}
test_so.cpp

Code: Select all

#include &quote;so.h&quote;

char moduledir&#1111;] = &quote;./modules&quote;;
#define PARENT_DIR &quote;..&quote;
#define CURRENT_DIR &quote;.&quote;

int main(int argc, char *argv&#1111;])
{
	//------ load the shared object

	// pointers for a directory and an entry
	DIR *dir;
	struct dirent *ep;

	// temporary buffer
	char buffer&#1111;200];

	// a module
	module mod;

	// grab the directory
	dir = opendir(moduledir);

	bool dophp = false;
	if ( dir )
	{
		// read all the entries -- asume there are only shared objects inside
		while ( (ep = readdir(dir)) )
		{
			if ( !strcmp(ep->d_name, PARENT_DIR) || !strcmp(ep->d_name, CURRENT_DIR) ) continue;

			// try to load
			sprintf(buffer, &quote;%s/%s&quote;, moduledir, ep->d_name);
			if ( loadmodule(&mod, buffer) )
			{
				dophp = true;
				printf(&quote;successfully loaded module\n&quote;);
			}
			else
				printf(&quote;module loading failure\n&quote;);
		}
		closedir(dir);
	}
	else
	{
		perror(&quote;Error opening dir \&quote;./modules\&quote;\n&quote;);
		return -1;
	}

	if ( dophp )
	{
		printf(&quote;Getting ready to run the PHP ...\n&quote;);
		(*mod.init)(argc,argv);

		unloadmodule(&mod);
	}

	return 0;
}
Makefile

Code: Select all

TOOL=gcc
INC=include
SRC=src

all: test_so.o so.o
	$(TOOL) -lgcc -lstdc++ -ldl -o test_so so.o test_so.o

so.o: $(SRC)/so.cpp $(INC)/so.h
	$(TOOL) -I$(INC) -c -Wall $(SRC)/so.cpp

test_so.o: test_so.cpp $(INC)/so.h
	$(TOOL) -I$(INC) -c -Wall test_so.cpp
	
clean:
	rm test_so test_so.o so.o
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Hmm... well done and welcome to the forums. Its been a good while since we've had such a "non-php PHP" related issue :P

Hope to see you around some more... ;)
msangine
Forum Newbie
Posts: 1
Joined: Wed Sep 14, 2005 9:26 am

undefined symbol: ap_loaded_modules

Post by msangine »

I am facing the same problem of "undefined symbol: ap_loaded_modules" when trying to run php scripts in commandline. Pl let me know if you found any answer for this one.

thanks.
Post Reply