Skip to content

Commit

Permalink
initial translation in reference/ffi
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardolara committed Nov 29, 2024
1 parent da5f25d commit 04c1038
Show file tree
Hide file tree
Showing 8 changed files with 1,432 additions and 1 deletion.
2 changes: 1 addition & 1 deletion reference/ffi/configure.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: cffb5f52894aa8a29109e3802e2257c56b51bcb6 Maintainer: AdaiasMagdiel Status: ready --><!-- CREDITS: AdaiasMagdiel -->
<!-- EN-Revision: 9e0804888ae46a50f28d98514a8d5e70a34e069c Maintainer: leonardolara Status: ready --><!-- CREDITS: AdaiasMagdiel -->

<section xml:id="ffi.installation" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
&reftitle.install;
Expand Down
344 changes: 344 additions & 0 deletions reference/ffi/examples.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 8859c8b96cd9e80652813f7bcf561432a5e9f934 Maintainer: leonardolara Status: ready -->

<chapter xml:id="ffi.examples" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
&reftitle.examples;
<section xml:id="ffi.examples-basic">
<title>Uso básico da FFI</title>
<para>
Antes de mergulhar nos detalhes da API da FFI, seguem abaixo alguns exemplos
demonstrando a simplicidade de seu uso para tarefas regulares.
</para>
<note>
<para>
Alguns destes exemplos requerem o <filename>libc.so.6</filename> e por isso não
funcionarão em sistemas onde ele não estiver disponível.
</para>
</note>
<para>
<example xml:id="ffi.examples.function">
<title>Chamando uma função de uma biblioteca compartilhada</title>
<programlisting role="php">
<![CDATA[
<?php
// cria o objeto FFI, carregando a libc e exportando a função printf()
$ffi = FFI::cdef(
"int printf(const char *format, ...);", // esta é uma declaração normal em C
"libc.so.6");
// chama printf() da linguagem C
$ffi->printf("Olá, %s!\n", "mundo");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Olá, mundo!
]]>
</screen>
</example>
</para>
<note>
<para>
Observe que algumas funções de C precisam de convenções específicas de chamada, por exemplo <literal>__fastcall</literal>,
<literal>__stdcall</literal> ou <literal>,__vectorcall</literal>.
</para>
</note>
<para>
<example xml:id="ffi.examples.structure">
<title>Chamando uma função e retornando uma estrutura através de um argumento</title>
<programlisting role="php">
<![CDATA[
<?php
// cria uma ligação a gettimeofday()
$ffi = FFI::cdef("
typedef unsigned int time_t;
typedef unsigned int suseconds_t;
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
int gettimeofday(struct timeval *tv, struct timezone *tz);
", "libc.so.6");
// cria estrutura de dados em C
$tv = $ffi->new("struct timeval");
$tz = $ffi->new("struct timezone");
// chama a função C gettimeofday()
var_dump($ffi->gettimeofday(FFI::addr($tv), FFI::addr($tz)));
// acessa campo da estrutura de dados C
var_dump($tv->tv_sec);
// exibe toda a estrutura de dados C
var_dump($tz);
?>
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
int(0)
int(1555946835)
object(FFI\CData:struct timezone)#3 (2) {
["tz_minuteswest"]=>
int(0)
["tz_dsttime"]=>
int(0)
}
]]>
</screen>
</example>
</para>
<para>
<example xml:id="ffi.examples.variable-existing">
<title>Acessando variáveis C existentes</title>
<programlisting role="php">
<![CDATA[
<?php
// cria o objeto FFI, carregando a libc e exportando a variável errno
$ffi = FFI::cdef(
"int errno;", // esta é uma declaração normal em C
"libc.so.6");
// exibe o errno de C
var_dump($ffi->errno);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
int(0)
]]>
</screen>
</example>
</para>
<para>
<example xml:id="ffi.examples.variable-creating">
<title>Criando e modificando variáveis C</title>
<programlisting role="php">
<![CDATA[
<?php
// cria uma nova variável int em C
$x = FFI::new("int");
var_dump($x->cdata);
// atribuição simples
$x->cdata = 5;
var_dump($x->cdata);
// atribuição composta
$x->cdata += 2;
var_dump($x->cdata);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
int(0)
int(5)
int(7)
]]>
</screen>
</example>
</para>
<para>
<example xml:id="ffi.examples.array">
<title>Trabalhando com arrays C</title>
<programlisting role="php">
<![CDATA[
<?php
// cria estrutura de dados C
$a = FFI::new("long[1024]");
// trabalhando com ela como um array normal do PHP
for ($i = 0; $i < count($a); $i++) {
$a[$i] = $i;
}
var_dump($a[25]);
$sum = 0;
foreach ($a as $n) {
$sum += $n;
}
var_dump($sum);
var_dump(count($a));
var_dump(FFI::sizeof($a));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
int(25)
int(523776)
int(1024)
int(8192)
]]>
</screen>
</example>
</para>
<para>
<example xml:id="ffi.examples.enum">
<title>Trabalhando com enumerações C</title>
<programlisting role="php">
<![CDATA[
<?php
$a = FFI::cdef('typedef enum _zend_ffi_symbol_kind {
ZEND_FFI_SYM_TYPE,
ZEND_FFI_SYM_CONST = 2,
ZEND_FFI_SYM_VAR,
ZEND_FFI_SYM_FUNC
} zend_ffi_symbol_kind;
');
var_dump($a->ZEND_FFI_SYM_TYPE);
var_dump($a->ZEND_FFI_SYM_CONST);
var_dump($a->ZEND_FFI_SYM_VAR);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
int(0)
int(2)
int(3)
]]>
</screen>
</example>
</para>
</section>
<section xml:id="ffi.examples-callback">
<title>Funções de retorno PHP</title>
<para>
É possível atribuir um closure do PHP a uma variável nativa do tipo ponteiro de função
ou passá-lo como um argumento de função:
<example>
<title>Atribuindo um <classname>Closure</classname> PHP a um ponteiro de função C</title>
<programlisting role="php">
<![CDATA[
<?php
$zend = FFI::cdef("
typedef int (*zend_write_func_t)(const char *str, size_t str_length);
extern zend_write_func_t zend_write;
");
echo "Olá, Mundo 1!\n";
$orig_zend_write = clone $zend->zend_write;
$zend->zend_write = function($str, $len) {
global $orig_zend_write;
$orig_zend_write("{\n\t", 3);
$ret = $orig_zend_write($str, $len);
$orig_zend_write("}\n", 2);
return $ret;
};
echo "Olá, Mundo 2!\n";
$zend->zend_write = $orig_zend_write;
echo "Olá, Mundo 3!\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Olá, Mundo 1!
{
Olá, Mundo 2!
}
Olá, Mundo 3!
]]>
</screen>
</example>
Embora isso funciona, esta funcionalidade não é suportada em todas as plataformas libffi, não é eficiente
e apresenta vazamento de recursos ao final da requisição.
<tip>
<simpara>
Portanto, é recomendado minimizar o uso de chamadas de retorno do PHP.
</simpara>
</tip>
</para>
</section>

<section xml:id="ffi.examples-complete">
<title>Um exemplo completo de PHP/FFI/pré-carregamento</title>
<informalexample>
<simpara><filename>php.ini</filename></simpara>
<programlisting role="ini">
<![CDATA[
ffi.enable=preload
opcache.preload=preload.php
]]>
</programlisting>
<simpara><filename>preload.php</filename></simpara>
<programlisting role="php">
<![CDATA[
<?php
FFI::load(__DIR__ . "/dummy.h");
opcache_compile_file(__DIR__ . "/dummy.php");
?>
]]>
</programlisting>
<simpara><filename>dummy.h</filename></simpara>
<programlisting role="c">
<![CDATA[
#define FFI_SCOPE "DUMMY"
#define FFI_LIB "libc.so.6"
int printf(const char *format, ...);
]]>
</programlisting>
<simpara><filename>dummy.php</filename></simpara>
<programlisting role="php">
<![CDATA[
<?php
final class Dummy {
private static $ffi = null;
function __construct() {
if (is_null(self::$ffi)) {
self::$ffi = FFI::scope("DUMMY");
}
}
function printf($format, ...$args) {
return (int) self::$ffi->printf($format, ...$args);
}
}
?>
]]>
</programlisting>
<simpara><filename>test.php</filename></simpara>
<programlisting role="php">
<![CDATA[
<?php
$d = new Dummy();
$d->printf("Olá, %s!\n", "mundo");
?>
]]>
</programlisting>
</informalexample>
</section>
</chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
Loading

0 comments on commit 04c1038

Please sign in to comment.