Desenvolvendo Extensões
- Discute como desenvolver extensões para o PHP, incluindo como gerar o esqueleto de uma extensão, compilá-la, lidar com tipos de dados, arrays, recursos, orientação a objetos e mais.
Hello World
- php,pear, pecl, linux, plesk, puppet...
- pecl.php.net/augeas
- spamassassin php api
- api api api api api api api api
- wordpress
3.
Por que vocêestá aqui?
(nesta sala, não no universo)
4.
pecl
- php extensioncommunity library
- dizem que se lê “pickle”
- ou no brasil: “pê” “ê” (ou “é”) “cê” “éle”
5.
Motivos para criaruma extensão
- performance
- “esconder o código” do cliente
- acessar funções de uma biblioteca C
- modificar o comportamento do PHP
6.
acessar funções deuma biblioteca em C
"It is a glue language that glues the web
server to all the interesting backend
libraries available out there." *
Rasmus Lerdorf
* http://www.urgig.com/int/0107_rl_a_int.html
montando o ambiente- windows
- sim, é possível; sim, é mais chato que no linux
- visual c++ 2008 (express edition é de graça)
- microsoft platform sdk
- várias bibliotecas necessárias pelo PHP
- variáveis de ambiente no console do visual studio
- processo completo:
http://wiki.php.net/internals/windows/stepbystepbuild
14.
código fonte doPHP
- php.net/downloads
- 5.3.3
- extraia p/ algum diretório
- em windows, não use caminhos que
contenham espaços
- cd php-src/ext
15.
compilando a extensão- linux
$ cd ext/minhaextensao
$ phpize
$ ./configure
$ make
$ (sudo) make install
“extension=minhaextensao.so” no php.ini
16.
compilando a extensão- windows
- siga todos os passos da etapa de setup do ambiente
- garanta que a extensão está no diretório ext/
- abra o Visual Studio Command Prompt
> vcvars32.bat
> buildconf
> configure –disable-all –enable-minhaextensao=shared
–enable-cli
> nmake
- dentro de Release_TS estará php_minhaextensao.dll
gerando o esqueletode uma extensão
- é tão chato que foi preciso criar um
script pra isso
- php-src/ext/ext_skel
- php-src/ext/ext_skel_win32.php
* precisa de CygWin instalado
* gera o arquivo .dsp do VisualStudio
19.
gerando o esqueletode uma extensão
./ext_skel –extname=minhaextensao
.cvsignore (renomeie para .gitignore =P)
config.m4 (config script linux)
config.w32 (config script windows)
CREDITS (seu nome e seu e-mail)
EXPERIMENTAL (not for use in production)
minhaextensao.c (código da extensão)
minhaextensao.php (script de teste)
php_minhaextensao.h (headers)
tests/001.phpt (primeiro teste)
20.
minhaextensao.c – moduleentry
essa estrutura vai armazenar todas as
informações sobre sua extensão
21.
minhaextensao.c - functions
Sim,a última linha tem sempre que ser {NULL, NULL, NULL}, isso indica
para a Zend Engine que a lista de funções acabou.
Internamente, confirm_minha_extensao_compiled será chamada de
zif_confirm_minhaextensao_compiled. (zif = zend internal function)
config.m4
símbolos de umabiblioteca são todos os elementos
visíveis ao seu usuário, podem ser classes, funções,
estruturas de dados, etc...
29.
bibliotecas externas –embutir ou linkar?
- em windows é preferível embutir a biblioteca
externa, pois o usuário final só precisa instalar
sua dll (php_minhaextensao.dll)
- em linux, verifique se as distribuições possuem
pacotes para a biblioteca em questão;
- se for embutir, verifique se a licença da
biblioteca permite isso
PHP_MINIT_FUNCTION
- executado umavez para cada processo
- cli/cgi/multithread sapi => executa apenas
uma vez (apache2-worker)
- sempre que houver fork(); inicia novamente
o ambiente (mod_php no apache2-prefork)
- registrar classes, constantes, configurações
php.ini...
os outros tiposque não tem tanta graça
zval *meuzval;
ZVAL_NULL(meuzval);
ZVAL_LONG(meuzval, 1408);
/* bool usa o mesmo espaço de long */
ZVAL_BOOL(meuzval, 1);
ZVAL_STRING(meuzval, “tchananan”, 0);
53.
daqui a poucovamos discutir sobre
resource e objetos, guentaí
54.
retornando valores emfunções
- já vimos que existe um tal de
return_value em algum lugar
- podemos manipular seu valor e deixar
que o php o retorne
- ou podemos usar alguns atalhos
retornando os valoresem funções
RETURN_NULL();
RETURN_STRING(“bola”, 0);
RETURN_TRUE;
RETURN_FALSE;
RETURN_DOUBLE(3.14);
RETURN_LONG(1408);
e assim por diante...
recebendo valores emuma função
PHP_FUNCTION(minhaextensao_recebe_string)
{
char *param;
int param_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", ¶m, ¶m_len) == FAILURE) {
return;
}
php_printf("Obrigado por me passar como parametro: ");
PHPWRITE(param, param_len);
php_printf("n");
}
59.
recebendo valores emuma função
minhaextensao_recebe_string("eba!");
// Obrigado por me passar como parametro: eba!
minhaextensao_recebe_string();
// PHP Warning: minhaextensao_recebe_string()
expects exactly 1 parameter, 0 given
class bola {
public function __toString() {
return “bola”;
}
}
minhaextensao_recebe_string(new bola());
// Obrigado por me passar como parametro: bola
resources
- permite lidarcom estruturas mais
complexas em C e passá-las de um lado
para o outro;
- inicializados em PHP_MINIT_FUNCTION;
- usado em extensões procedurais;
65.
resources – inicialização/destruição
/*isso está no topo do minhaextensao.c */
static int le_minhaextensao;
static void php_minhaextensao_resource_destrutor(
zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
FILE *fp = (FILE *) rsrc->ptr;
fclose(fp);
}
PHP_MINIT_FUNCTION(minhaextensao)
{
le_minhaextensao = zend_register_list_destructors_ex(
php_minhaextensao_resource_destrutor,
NULL, "Resource da Minha Extensao",
module_number);
return SUCCESS;
}
66.
resources – criandoe retornando
PHP_FUNCTION(minhaextensao_resource)
{
FILE *fp;
fp = fopen("/tmp/arquivo", "r");
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Naaaaaao");
RETURN_FALSE;
}
ZEND_REGISTER_RESOURCE(return_value, fp, le_minhaextensao);
}
$ php -r 'var_dump(minhaextensao_resource());'
resource(4) of type (Resource da Minha Extensao)
Declarando uma classe- propriedades
int zend_declare_property(zend_class_entry *ce, char *name,
int name_length, zval *property, int access_type TSRMLS_DC);
int zend_declare_property_null(zend_class_entry *ce, char *name,
int name_length, int access_type TSRMLS_DC);
int zend_declare_property_bool(zend_class_entry *ce, char *name,
int name_length, long value, int access_type TSRMLS_DC);
int zend_declare_property_double(zend_class_entry *ce, char *name,
int name_length, double value, int access_type TSRMLS_DC);
int zend_declare_property_string(zend_class_entry *ce, char *name,
int name_length, char *value, int access_type TSRMLS_DC);
zval *zend_read_property(zend_class_entry *scope, zval *object,
char *name, int name_length, zend_bool silent TSRMLS_DC);
Créditos: Erick Tedeschi
77.
declarando uma classe- constantes
int zend_declare_class_constant(zend_class_entry *ce,
char *name, size_t name_len, zval *value TSRMLS_DC);
int zend_declare_class_constant_long(zend_class_entry *ce,
char *name, size_t name_len, long value TSRMLS_DC);
int zend_declare_class_constant_bool(zend_class_entry *ce,
char *name, size_t name_len, zend_bool value TSRMLS_DC);
int zend_declare_class_constant_double(zend_class_entry *ce,
char *name, size_t name_len, double value TSRMLS_DC);
int zend_declare_class_constant_string(zend_class_entry *ce,
char *name, size_t name_len, char *value TSRMLS_DC);
Créditos: Erick Tedeschi