Criando Extensões PHP – Trabalhando com resources

Bem, este tópico eu iniciei para esclarecer algumas duvidas com um membro, o Helder, mas também é aberto a todos, claro.
Primeiro postei este, pois era a urgência, mas pretendo fortemente iniciar uma serie de posts sobre o assunto.

Bem, vamos la.

Muitas vezes você precisa retornar uma janela, retornar algum tipo de variável que o PHP não possui.
Pois bem, vou utilizar aqui o exemplo, utilizando o FILE ok? Nesse caso, o FILE será nosso recurso.

Para criarmos recursos, precisamos de 3 coisas: o destrutor deste recurso, linkar esse descructor, e utilizar uma função especifica para retornar o resource.

Primeiro criamos uma variável estática global, que será o ponteiro para nosso resource.

static int le_file

depois disso, vamos criar a função que destruirá nosso resource. Isso é uma proteção da Zend, para garantir a destruição do resource ao terminar o script.

static void php_file_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
	FILE *fp = (FILE *)rsrc->ptr;
	fclose(fp);
}

Bem, repare que ele recebe uma variável do tipo zend_rsrc_list_entry. Na verdade é um void. Para quem não sabe, void não significa NADA como muitos dizem, void significa tudo, ela pode ser qualquer coisa, inclusive nada, loucura né? uaeuaeuh
Voltando, repare que eu recebo rsrc, mas converto um ponteiro dele em FILE depois, e fecho o arquivo normalmente.

Com tudo isso criado, precisamos dizer que esta função é destrutora de le_file. Para isso, utilizamos a função PHP_MINIT_FUNCTION, que é como se fosse o main do C. Ela é a primeira coisa executada do seu módulo. Então nela dizemos quem é nosso detrutor no le_file.

PHP_MINIT_FUNCTION(sdlmixer)
{
	le_file = zend_register_list_destructors_ex(php_file_close, NULL, "Nome do meu Resouce", module_number);
	return SUCCESS;
}

Assim, já temos tudo pronto. O primeiro parâmetro é a função destutora. Repare em Nome do meu Resouce. Ali será o nome do seu resource =D. Quando você der um var_dump(), ele sairá la, dizendo que o resource é do tipo "Nome do meu Resource". module_number é pre-definido da Zend.

Ok, tudo pronto, vamos criar nossa função

PHP_FUNCTION(OpenFile)
{
	char *filename;
	int filename_len;
	FILE *fp = NULL;
	
	int result;
	
	result = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len);
	
	if(result == FAILURE) 
	{
		return;
	}
	
	fp = fopen(filename, "r");
	
	ZEND_REGISTER_RESOURCE(return_value, fp, le_file);
}

Assim, podemos utilizar nossa função no PHP assim:

$file = OpenFile("MeuArquivo.txt");
var_dump($file);

Show neh?

Agora vamos voltar nosso resource.

PHP_FUNCTION(CloseFile)
{
	File *fp = NULL;
	
	zval *resource;
	
	int result;
	int res_type = -1; 
	
	result = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &resource);
	
	if(result == FAILURE) 
	{
		return;
	}
	
	fp = (FILE *)zend_list_find(Z_RESVAL_P(resource), &res_type);
	
	fclose(fp, -1);
	
	return;
}

auehuae é isso, pode parecer loucura, mas o difícil foi descobrir isso, agora a coisa ficou muito claro, muito fácil isso =D

Imagine assim, você precisa de um destrutor (sem ele não funciona), depois vc converte em resource (ZEND_REGISTER_RESOURCE), depois a gente converte de volta no formato original (zend_list_find).

Fia ai a dica 😉