<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Head Like a Hole</title>
	<atom:link href="http://www.setantas.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.setantas.net/blog</link>
	<description></description>
	<lastBuildDate>Tue, 22 Mar 2011 15:30:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Python bindings para libepub usando Shiboken</title>
		<link>http://www.setantas.net/blog/2011/03/09/python-bindings-para-libepub-usando-shiboken/</link>
		<comments>http://www.setantas.net/blog/2011/03/09/python-bindings-para-libepub-usando-shiboken/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 03:10:12 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[pro]]></category>
		<category><![CDATA[pt]]></category>
		<category><![CDATA[bindings]]></category>
		<category><![CDATA[ebooks]]></category>
		<category><![CDATA[ePub]]></category>
		<category><![CDATA[PySide]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Shiboken]]></category>

		<guid isPermaLink="false">http://www.setantas.net/blog/?p=517</guid>
		<description><![CDATA[Tenho um Kindle, gosto muito dele, mas infelizmente não posso dizer o mesmo sobre o formato usado para os livros. Não que eu tenha feito um estudo detalhado do formato mobi e chegado a conclusão que ele é tecnicamente inferior. Não. O problema é que ePub é tão mais popular, o que significa mais livros, [...]]]></description>
			<content:encoded><![CDATA[<p>Tenho um <a href="http://twitpic.com/3ucxtj">Kindle</a>, gosto muito dele, mas infelizmente não posso dizer o mesmo sobre o formato usado para os livros. Não que eu tenha feito um estudo detalhado do formato mobi e chegado a conclusão que ele é tecnicamente inferior. Não. O problema é que <a title="Wikipedia: ePub" href="http://en.wikipedia.org/wiki/EPUB">ePub</a> é tão mais popular, o que significa mais livros, e mais ferramentas com as quais brincar. <a href="http://calibre-ebook.com/">Calibre</a> é ótimo para converter formatos de eBooks, mas eu prefiro a simplicidade de baixar um livro, copiar pro dispositivo e já sair lendo.</p>
<p>Quando meu Kindle não está à mão, meu leitor substituto é um N900 com <a title="eBook reader for Maemo 5" href="http://juhanagsoc.wordpress.com/">MeBook</a>, um dos meus aplicativos preferidos &#8211; ele procura por livros (no formato ePub) no <a title="Feedbooks" href="http://www.feedbooks.com/">Feedbooks</a>, baixa pro dispositivo e os mostra numa lista bem bacana, com capas e tudo. Examinando o código fonte do MeBook aprendi que ele usa a <a title="eBook tools" href="http://sourceforge.net/projects/ebook-tools/">libepub</a> para ler eBooks ePub, então pensei que seria interessante fazer bindings Python para <strong>libepub</strong>. E aqui estamos.</p>
<p>Ah, e mais uma coisa antes de começarmos, encontrei um projeto Python no github chamado <a href="https://github.com/jharjono/libepub">libepub</a>. Não verifiquei ainda, mas o menciono aqui pelo bem da informação.</p>
<h2>Shiboken</h2>
<p><a title="Shiboken" href="http://www.setantas.net/blog/2009/08/31/shiboken/" target="_self">Shiboken</a> é a ferramenta de renome mundial usada para gerar o mundialmente famoso <a title="PySide" href="http://pyside.org">PySide</a> (que ocore ter alcançado a versão <a title="PySide: Python for Qt 1.0 released!" href="http://www.pyside.org/2011/03/pyside-python-for-qt-1-0-released/">1.0</a> semana passada &#8211; viva!) Ela é uma das melhores ferramentas disponíveis para gerar bindings Python para bibliotecas C++. Mas isso sou eu falando &#8211; eu nela. Contudo, <strong>libepub</strong> é escrita em C, e mesmo que Shiboken possa gerar bindings para um punhado de funções globais e juntá-las num módulo Python, fica uma porcaria. De forma que terei de fazer algumas preparações para que a <strong>libepub</strong> apareça bela em Python.</p>
<blockquote><p><strong>Pré-requisitos:</strong> arquivos de desenvolvimento (i.e. os cabeçalhos) para <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">ApiExtractor</a>, <a title="GeneratorRunner 0.6" href="http://pyside.org/docs/generatorrunner/">GeneratorRunner</a>, <a title="Shiboken" href="http://pyside.org/docs/shiboken/">Shiboken</a>, e <strong>libepub</strong>. (Para usuários de Debian/Ubuntu isto significa: <strong>libapiextractor-dev</strong>, <strong>libgenrunner-dev</strong>, <strong>libshiboken-dev</strong>, and <strong>libepub-dev</strong>.) E o compilador C++ mais o CMake, é claro.</p></blockquote>
<p><strong>Lembrete:</strong> ApiExtractor, GeneratorRunner e Shiboken são feitos com Qt (somente módulos principais, nenhuma delas tem ui), mas os bindings gerados não dependem da Qt de forma alguma. Exceto, obviamente, se a biblioteca para qual os bindings serão gerados já a use.</p>
<h3>libepub</h3>
<p>Primeiro, vamos dar uma olhada na <strong>libepub</strong>. Ela tem três estruturas usadas como ponteiros opacos:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// Contem informacao sobre o arquivo ePub.</span><br />
<span style="color: #0000ff;">struct</span> epub<span style="color: #008080;">;</span><br />
<span style="color: #666666;">// Objeto iterador para o indice.</span><br />
<span style="color: #0000ff;">struct</span> titerator<span style="color: #008080;">;</span><br />
<span style="color: #666666;">// Objeto iterador para o conteudo do livro.</span><br />
<span style="color: #0000ff;">struct</span> eiterator<span style="color: #008080;">;</span></div></div>
<p>Se você quiser ler o conteúdo de um arquivo ePub, chame a função que irá criar uma estrutura epub, itere por seu índice com um titerator, e depois pelos conteúdos mesmos usando um eiterator.</p>
<p>A maioria das funções seguem aquele formato &#8220;C orientado a objetos&#8221; visto em outras bibliotecas, com o primeiro argumento sendo um ponteiro para a estrutura que representa o <em>&#8220;this&#8221;</em> ou <em>&#8220;self&#8221;</em> em linguagens OO. Exemplos:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span><br />
epub_dump<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> epub<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span><br />
epub_get_metadata<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> epub,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">enum</span> epub_metadata type,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">int</span><br />
epub_get_data<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> epub,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> name,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></div>
<h3>CMake</h3>
<p>Usarei CMake como o sistema de compilação dos bindings pois me sinto confortável com ele &#8211; é o mesmo usado no PySide e no conjunto de ferramentas de geração do Shiboken. Não darei muita atenção à esta parte do processo, apenas veja os arquivos <strong>CMakeLists.txt</strong>; explicação mais detalhada sobre o processo de compilar um binding pode ser encontrada em <a title="PySide Binding Generation Tutorial" href="http://developer.qt.nokia.com/wiki/Category:LanguageBindings::PySide::Shiboken::PySide_Binding_Generation_Tutorial">PySide Binding Generation Tutorial</a>. Para informação realmente básica, veja <a title="PySide CMake Primer" href="http://developer.qt.nokia.com/wiki/PySide_CMake_Primer">PySide CMake Primer</a>.</p>
<h2>C++ Wrapper feito à mão para uma biblioteca em C</h2>
<p>Para gerar bindings Python para uma biblioteca C++, o sujeito precisa escrever uma descrição XML chamada type system, que declarará o quê precisa ser exposto para Python, e o quê sofrerá modificação: funções globais, classes, namespaces, enums. Por exemplo, se em C++ temos a classe <code class="codecolorer cpp default"><span class="cpp">Rectangle</span></code>, eu a declararia no type system dessa forma:</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'Rectangle'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>Todos os métodos pertencentes à <code class="codecolorer cpp default"><span class="cpp">Rectangle</span></code> serão expostos em Python automaticamente. O mesmo não vale para as funções em C que representam os métodos para a estrutura epub. Infelizmente não há modo de dizer para o gerador Shiboken que quero a estrutura epub e suas funções representadas como uma classe com métodos, sendo assim precisamos escrever um fino envoltório C++ ao redor das estruturas C. Isto seria um bocado de trabalho para uma grande biblioteca C, mas mesmo com uma minúscula sinto o desconforto de precisar recorrer a este tipo de gambiarra. O type system deveria ser expressivo o bastante para gerar bindings para estruturas e funções em C como se elas fossem objetos e métodos apropriados. Vou marcar isto para futuras melhorias comunitárias/fora-do-trabalho no Shiboken.</p>
<p>Vejamos um pedaço de código do arquivo<a title="epub_cpp_wrappers.h @ 757d8dc" href="https://github.com/setanta/python-epub/blob/757d8dcd34943dd71495959a81fb15ce07896898/epub_cpp_wrappers.h">epub_cpp_wrapper.h</a>:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> EPub <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; ...<br />
<br />
&nbsp; &nbsp; ~EPub<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> epub_close<span style="color: #008000;">&#40;</span>m_epub<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">inline</span> EPub<span style="color: #000040;">*</span><br />
&nbsp; &nbsp; open<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> filename, <span style="color: #0000ff;">int</span> debug <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> book <span style="color: #000080;">=</span> epub_open<span style="color: #008000;">&#40;</span>filename, debug<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>book<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">new</span> EPub<span style="color: #008000;">&#40;</span>book<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">void</span> dump<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> epub_dump<span style="color: #008000;">&#40;</span>m_epub<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">int</span><br />
&nbsp; &nbsp; get_data<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> name, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> data<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_get_data<span style="color: #008000;">&#40;</span>m_epub, name, data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; ...<br />
<br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> EPub<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> ptr<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> m_epub<span style="color: #008000;">&#40;</span>ptr<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; EPub<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EPub<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> other<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; EPub<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EPub<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> other<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> m_epub<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>Note que todos os métodos são marcados como <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">inline</span></span></code> para fazer este envoltório o mais fino possível. (GCC, estou olhando pra você!)</p>
<h3>Epub::open</h3>
<p>A função <code class="codecolorer cpp default"><span class="cpp">epub_open</span></code> se torna o método estático <code class="codecolorer cpp default"><span class="cpp">EPub<span style="color: #008080;">::</span><span style="color: #007788;">open</span></span></code> que retornará um novo objeto <code class="codecolorer cpp default"><span class="cpp">EPub</span></code> para o arquivo ePub dado pelo parâmetro <code class="codecolorer cpp default"><span class="cpp">filename</span></code>, ou um null pointer se o arquivo for inválido ou não existir.<br />
O construtor para esta classe foi feito privado de forma que o único modo de criar objetos EPub é via <code class="codecolorer cpp default"><span class="cpp">EPub<span style="color: #008080;">::</span><span style="color: #007788;">open</span></span></code>, que nunca criará um objeto <code class="codecolorer cpp default"><span class="cpp">EPub</span></code> inválido.</p>
<h3>~Epub</h3>
<p>Em C o responsável por liberar a estrutura epub é <code class="codecolorer cpp default"><span class="cpp">epub_close</span></code>, mas não criarei um método <code class="codecolorer cpp default"><span class="cpp">EPub<span style="color: #008080;">::</span><span style="color: #007788;">close</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code>, pois o equivalente C++ para ele é o destrutor da classe.</p>
<p>Um binding Python gerado para o que temos até agora seria mais ou menos assim:</p>
<div class="codecolorer-container python geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> epub<br />
book = epub.<span style="color: black;">EPub</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sample.epub'</span><span style="color: black;">&#41;</span><br />
title = book.<span style="color: black;">get_metadata</span><span style="color: black;">&#40;</span>epub.<span style="color: black;">EPUB_TITLE</span><span style="color: black;">&#41;</span></div></div>
<p>Claro que não expliquei como isto seria gerado, que o módulo se chamaria <code class="codecolorer python default"><span class="python">epub</span></code>, o que é <code class="codecolorer python default"><span class="python">epub.<span style="color: black;">EPUB_TITLE</span></span></code>, e como Python saberia o que fazer com <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span></span></code>, mas tenhamos paciência.</p>
<h3>Movendo enums por aí</h3>
<p><code class="codecolorer cpp default"><span class="cpp">EPUB_TITLE</span></code> é um valor vindo do enum <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code>, se ambos forem exportados para Python conforme estão, eles terão esta aparência:</p>
<div class="codecolorer-container python geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> epub<br />
epub.<span style="color: black;">epub_metadata</span><br />
epub.<span style="color: black;">EPUB_TITLE</span></div></div>
<p>Assim fica bem feio e fuleiro. Já que <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code> é um enum relacionado ao objeto epub (como nos informa o prefixo <strong>epub_</strong>), será natural que ele seja movido para dentro da class EPub. No meu mundo de fantasia, a tag do type system que descreve um enum C++ para Python teria a opção de movê-lo para dentro de outro objeto, e também de ser renomeado. Algo desse tipo:</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enum-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'epub_metadata'</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">rename</span>=<span style="color: #ff0000;">'metatada'</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">move-into</span>=<span style="color: #ff0000;">'EPub'</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">remove-enum-value-prefix</span>=<span style="color: #ff0000;">'EPUB_'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>E aqui temos outro item para a lista de &#8220;por fazer&#8221; do Shiboken. Enquanto esta funcionalidade não é implementada, terei de fazê-lo manualmente.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> EPub <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">enum</span> metadata <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ID <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_ID<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; TITLE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_TITLE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; CREATOR <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_CREATOR<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; CONTRIB <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_CONTRIB<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; SUBJECT <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_SUBJECT<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; PUBLISHER <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_PUBLISHER<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; DESCRIPTION <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_DESCRIPTION<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; DATE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_DATE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; TYPE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_TYPE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; FORMAT <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_FORMAT<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; SOURCE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_SOURCE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; LANG <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_LANG<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; RELATION <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_RELATION<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; COVERAGE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_COVERAGE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; RIGHTS <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_RIGHTS<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; META <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_META<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span><br />
&nbsp; &nbsp; get_metadata<span style="color: #008000;">&#40;</span>metadata type, <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_get_metadata<span style="color: #008000;">&#40;</span>m_epub,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;epub_metadata<span style="color: #008000;">&#40;</span>type<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>Os valores do enum <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code> foram convertidos para <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">int</span></span></code> para impedir o <strong>ApiExtractor</strong> de emitir toda sorte de warnings dizendo que ele não sabe quem são esses caras.</p>
<p>De qualquer modo, é terrível&#8230; ter esse gerador incrementado, e ter de escrever tudo isso&#8230; nãããão!</p>
<h3>TIterator e EIterator</h3>
<p>As estruturas C <code class="codecolorer cpp default"><span class="cpp">titerator</span></code> e <code class="codecolorer cpp default"><span class="cpp">eiterator</span></code> serão envolvidas pelas class C++ <code class="codecolorer cpp default"><span class="cpp">TIterator</span></code> e <code class="codecolorer cpp default"><span class="cpp">EIterator</span></code>, respectivamente, e como a classe <code class="codecolorer cpp default"><span class="cpp">EPub</span></code> seus construtores serão privados.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> TIterator <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">enum</span> type <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; NAVMAP <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>TITERATOR_NAVMAP<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; GUIDE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>TITERATOR_GUIDE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; PAGES <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>TITERATOR_PAGES<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; ~TIterator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> epub_free_titerator<span style="color: #008000;">&#40;</span>m_iter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> isValid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_tit_curr_valid<span style="color: #008000;">&#40;</span>m_iter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">friend</span> <span style="color: #0000ff;">class</span> EPub<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> TIterator<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> iter<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">:</span> m_iter<span style="color: #008000;">&#40;</span>iter<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> m_iter<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>Novas instâncias de <code class="codecolorer cpp default"><span class="cpp">TIterator</span></code> e <code class="codecolorer cpp default"><span class="cpp">EIterator</span></code> são criadas por métodos de <code class="codecolorer cpp default"><span class="cpp">EPub</span></code>, por isso ela deve ser feita amiga (<code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">friend</span></span></code>) das classes iteradoras.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> EPub <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> EIterator<span style="color: #000040;">*</span><br />
&nbsp; &nbsp; get_iterator<span style="color: #008000;">&#40;</span>EIterator<span style="color: #008080;">::</span><span style="color: #007788;">type</span> type, <span style="color: #0000ff;">int</span> opt <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">struct</span> eiterator<span style="color: #000040;">*</span> it <span style="color: #000080;">=</span> epub_get_iterator<span style="color: #008000;">&#40;</span>m_epub, eiterator_type<span style="color: #008000;">&#40;</span>type<span style="color: #008000;">&#41;</span>, opt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">new</span> EIterator<span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> TIterator<span style="color: #000040;">*</span><br />
&nbsp; &nbsp; get_titerator<span style="color: #008000;">&#40;</span>TIterator<span style="color: #008080;">::</span><span style="color: #007788;">type</span> type, <span style="color: #0000ff;">int</span> opt <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> it <span style="color: #000080;">=</span> epub_get_titerator<span style="color: #008000;">&#40;</span>m_epub, titerator_type<span style="color: #008000;">&#40;</span>type<span style="color: #008000;">&#41;</span>, opt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">new</span> TIterator<span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<h2>python-epub</h2>
<p>Agora é hora de dizer ao gerador o quê entra e o quê será modificado nos bindings.</p>
<h3>O cabeçalho global</h3>
<p>O cabeçalho global é um arquivo que inclui todos os outros cabeçalhos da biblioteca que será analizada. No cabeçalho global o desenvolvedor de bindings pode também adicionar algumas cláusulas, como um <code class="codecolorer cpp default"><span class="cpp"><span style="color: #339900;">#define</span></span></code> que irá causar alguma condição de mudança nos cabeçalhos da biblioteca alvo, que irá afetar o binding gerado.</p>
<p>O arquivo <a href="https://github.com/setanta/python-epub/blob/master/epub_global.h">epub_global.h</a> que uso aqui é muito simples:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#ifndef EPUB_GLOBAL_H</span><br />
<span style="color: #339900;">#define EPUB_GLOBAL_H</span><br />
<br />
<span style="color: #339900;">#include &amp;lt;epub.h&amp;gt;</span><br />
<span style="color: #339900;">#include &amp;lt;epub_shared.h&amp;gt;</span><br />
<span style="color: #339900;">#include &amp;lt;epub_version.h&amp;gt;</span><br />
<br />
<span style="color: #339900;">#include &quot;epub_cpp_wrappers.h&quot;</span><br />
<br />
<span style="color: #666666;">// ApiExtractor reclamara' se</span><br />
<span style="color: #666666;">// encontrar apenas pre-definicoes.</span><br />
<span style="color: #0000ff;">struct</span> titerator <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">struct</span> eiterator <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #339900;">#endif</span></div></div>
<p>Como o comentário nos diz, ApiExtractor não gosta quando encontra pré-declarações sem definições. Escolhi adicionar estas definições falsas para <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> titerator</span></code> e <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> eiterator</span></code>. (Por alguma razão o gerador nada diz sobre <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> epub</span></code>.) Outra opção seria não usar estas definições falsas, mas adicionar uma linha ao arquivo type system dizendo ao gerador para ignorar avisos relativos à estas estruturas.</p>
<h3>A descrição do Type System</h3>
<p>Aqui segue um pedaço de código do arquivo <a title="typesystem_epub.xml @ 78de928" href="https://github.com/setanta/python-epub/blob/78de92867f668d92a7610515eaeebe34487ebf03/typesystem_epub.xml">typesystem_epub.xml</a>.</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;typesystem</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">'epub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rejection</span> <span style="color: #000066;">enum-name</span>=<span style="color: #ff0000;">'epub_metadata'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'EPub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enum-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'metadata'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/typesystem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>O enum <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code> não é exportado para Python (ao menos não diretamente) e para evitar que o gerador emita seus alertas, ele precisa ser explicitamente rejeitado; seu substituto C++ é adicionado depois dentro do object-type EPub. O mesmo acontece com os outros enums.</p>
<p>Na notação do type system <code class="codecolorer xml default"><span class="xml">object-type</span></code> se refere aos objetos que são passados somente como ponteiros (como <code class="codecolorer cpp default"><span class="cpp">EPub</span></code>, cujos construtor e operador de cópia são privados). Se, de outro modo, o objeto pode ser passado como valor, ele deve ser declarado como <code class="codecolorer xml default"><span class="xml">value-type</span></code>, conforme nosso exemplo de <code class="codecolorer cpp default"><span class="cpp">Rectangle</span></code> mencionado anteriormente.</p>
<h3>O Protocolo de Iterador de Python</h3>
<p>Em Python, se um objeto suporta o <a href="http://docs.python.org/library/stdtypes.html#iterator-types">Protocolo de Iterador</a>, poderei usar em comandos <code class="codecolorer python default"><span class="python"><span style="color: #ff7700;font-weight:bold;">for</span></span></code>, desta forma:</p>
<div class="codecolorer-container python geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> epub <span style="color: #ff7700;font-weight:bold;">import</span> EPub, TIterator<br />
book = EPub.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">epub_file</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">for</span> toc_it <span style="color: #ff7700;font-weight:bold;">in</span> book.<span style="color: black;">get_titerator</span><span style="color: black;">&#40;</span>TIterator.<span style="color: black;">NAVMAP</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> toc_it.<span style="color: black;">isValid</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">continue</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'link : '</span> + toc_it.<span style="color: black;">link</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'label: '</span> + toc_it.<span style="color: black;">label</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>Seguir o Protocolo de Iterador de Python consiste tão somente de um objeto implementar os métodos <code class="codecolorer python default"><span class="python"><span style="color: #0000cd;">__iter__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code> e <code class="codecolorer python default"><span class="python">__next__<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>.</p>
<blockquote><p><strong>Nota:</strong> o nome correto para o método é <code class="codecolorer python default"><span class="python">next<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code> e não <code class="codecolorer python default"><span class="python">__next__<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>. Este é apenas um bug menor no gerador, que acabei de encontrar.</p></blockquote>
<p>O XML para adicionar as funcionalidades do protocolo de iterador à classe <code class="codecolorer python default"><span class="python">TIterator</span></code> será extenso, de forma que o partirei em duas partes, a primeira lidando com <a href="http://www.pyside.org/docs/apiextractor/typesystem_templates.html">templates de código do type system</a>.</p>
<h4>Os templates do Type System</h4>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;typesystem</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">'epub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__iter__'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_INCREF(%PYSELF);<br />
&nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = %PYSELF;<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/template<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__next__'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; if (%CPPSELF.next()) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__iter__'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; } else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PyErr_SetNone(PyExc_StopIteration);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/template<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; ...</div></div>
<p>Os métodos de iterador para <code class="codecolorer python default"><span class="python">TIterator</span></code> e <code class="codecolorer python default"><span class="python">EIterator</span></code> terão exatamente a mesma implementação, então é esperto usar os <a href="http://www.pyside.org/docs/apiextractor/typesystem_templates.html">templates</a> do type system, e ter o código, e seus eventuais bugs, num único lugar.</p>
<p>O <code class="codecolorer python default"><span class="python">iterator.<span style="color: #0000cd;">__iter__</span></span></code> método precisa apenas returnar o próprio objeto com seu contador de referências incrementado em um. <code class="codecolorer python default"><span class="python">iterator.__next__</span></code> chama o <code class="codecolorer cpp default"><span class="cpp">next<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> do objeto C++ subjacente (e também retorna a si próprio, e incrementa o refcounter), e sobe uma exceção Python <code class="codecolorer python default"><span class="python"><span style="color: #008000;">StopIteration</span></span></code> quando chega ao fim.</p>
<p>As <a href="http://www.pyside.org/docs/shiboken/typesystemvariables.html">variáveis do type system</a> <code class="codecolorer xml default"><span class="xml">%PYSELF</span></code>, <code class="codecolorer xml default"><span class="xml">%PYARG_0</span></code> e <code class="codecolorer xml default"><span class="xml">%CPPSELF</span></code> são substituídas por valores dependentes do contexto onde são usados (e.g. as classes <code class="codecolorer python default"><span class="python">TIterator</span></code> ou <code class="codecolorer python default"><span class="python">EIteration</span></code>). Verifique a <a href="http://www.pyside.org/docs/shiboken/typesystemvariables.html">documentation</a> para saber seus significados.</p>
<h4>Adicionando os métodos de iteração</h4>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'TIterator'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'next()'</span> <span style="color: #000066;">remove</span>=<span style="color: #ff0000;">'all'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'__iter__'</span> <span style="color: #000066;">return-type</span>=<span style="color: #ff0000;">'PyObject*'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__iter__'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/add-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'__next__'</span> <span style="color: #000066;">return-type</span>=<span style="color: #ff0000;">'PyObject*'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__next__'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/add-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/typesystem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Primeiro o <code class="codecolorer cpp default"><span class="cpp">next<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> original do C++ é removido, então aqueles para o protocolo de iterador do Python são adicionados, usando a tag <code class="codecolorer xml default"><span class="xml"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></span></code> para inserir o código personalizado definido anteriormente. A exatas mesmas linhas serão adicionadas à classe <code class="codecolorer python default"><span class="python">EIterator</span></code>.</p>
<h4>Só mais um pouco de gambiarras</h4>
<p>Apenas um obstáculo permanece no caminho de ter iteradores Python apropriados. Quando o comando <code class="codecolorer python default"><span class="python"><span style="color: #ff7700;font-weight:bold;">for</span></span></code> de Python for usado para iterar sobre um objeto iterável, na primeira rodada ele chama o método <code class="codecolorer python default"><span class="python"><span style="color: #0000cd;">__iter__</span></span></code> do objeto, e imediatamente após ele chama <code class="codecolorer python default"><span class="python">next</span></code>, e continua chamando <code class="codecolorer python default"><span class="python">next</span></code> para cada nova iteração.</p>
<p>O problema aqui é que o iterador C subjacente retorna um objeto levando conteúdo apropriado quando <code class="codecolorer python default"><span class="python"><span style="color: #0000cd;">__iter__</span></span></code> é chamado, então a forma como a iteração do <code class="codecolorer python default"><span class="python"><span style="color: #ff7700;font-weight:bold;">for</span></span></code> Python funciona fará o primeiro item válido ser pulado. Uma gambiarra para este caso é usar uma flag no wrapper C++ que verificará se o iterador acabou de ser criado, de forma que ele não pulará para o iterador seguinte quando <code class="codecolorer python default"><span class="python">next</span></code> for chamada pela primeira vez.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> TIterator <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> next<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_isFirst<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m_isFirst <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_tit_next<span style="color: #008000;">&#40;</span>m_iter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">friend</span> <span style="color: #0000ff;">class</span> EPub<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> TIterator<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> iter<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">:</span> m_iter<span style="color: #008000;">&#40;</span>iter<span style="color: #008000;">&#41;</span>, m_isFirst<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> m_iter<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">bool</span> m_isFirst<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>Pude ter esta liberdade porque <code class="codecolorer cpp default"><span class="cpp">TIterator</span></code> é uma classe completamente sob meu (eu, o desenvolvedor do binding) controle. Se <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> titerator</span></code> fosse uma classe C++ desde o começo, esta solução não seria a melhor. Talvez se a <strong>libshiboken</strong> (a biblioteca de apoio usada por todos os bindings gerados pelo Shiboken) fornecesse uma classe iteradora base para lidar com essa diferença particular entre iteradores Python e C++. Ou talvez as classes geradas, quando identificadas como iteráveis pela presença dos métodos do protocolo de iteração adicionados pelo desenvolvedor do binding, poderiam ter tal funcionalidade. A última opção me parece a melhor, e esse é mais um item pra minha lista de melhorias futuras.</p>
<h3>Conversões Personalizadas</h3>
<h4>Retornando valores unicode</h4>
<p>Os métodos <code class="codecolorer cpp default"><span class="cpp">EIterator<span style="color: #008080;">::</span><span style="color: #007788;">curr</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> e <code class="codecolorer cpp default"><span class="cpp">EIterator<span style="color: #008080;">::</span><span style="color: #007788;">curr_url</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> returnam valores do tipo <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span></span></code>, que não tem um conversor (<code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span></span></code> é que tem), por isso escrevi um código específico para converter isto para unicode do Python.</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;typesystem</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">'epub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'return_char_pointer'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; char* %0 = %CPPSELF.%FUNCTION_NAME();<br />
&nbsp; &nbsp; &nbsp; &nbsp; if (%0) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = PyUnicode_DecodeUTF8(%0, strlen(%0), &quot;strict&quot;);<br />
&nbsp; &nbsp; &nbsp; &nbsp; } else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Py_INCREF(Py_None);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = Py_None;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/template<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'EIterator'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'curr()'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'return_char_pointer'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'curr_url()'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'return_char_pointer'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/typesystem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h4>Modificando a assinatura de um método</h4>
<p>As assinaturas de alguns métodos C++ não podem ser automaticamente convertidas para código Python que faça sentido, então adicionei mais um pouco de código feito sob medida para tratar das situações caso a caso. Por exemplo, o método</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span><br />
EPub<span style="color: #008080;">::</span><span style="color: #007788;">get_metadata</span><span style="color: #008000;">&#40;</span>metadata type, <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></div>
<p>O argumento <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size</span></code> recebe um ponteiro para um int, que conterá o tamanho da lista de strings unicode retornada como <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span></span></code>. Em Python ele meramente retornará uma lista de objetos unicode, e a chamada à <code class="codecolorer cpp default"><span class="cpp">get_metadata</span></code> não precisa do argumento <code class="codecolorer cpp default"><span class="cpp">size</span></code>.</p>
<p>Creio que a descrição do type system será o bastante para ver como o sistema de modificação funciona.</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'EPub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enum-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'metadata'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'get_metadata(EPub::metadata,int*)'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-argument</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">'2'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;remove-argument</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-argument<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-argument</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">'return'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;replace-type</span> <span style="color: #000066;">modified-type</span>=<span style="color: #ff0000;">'PyTuple'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-argument<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; unsigned char** data = 0;<br />
&nbsp; &nbsp; &nbsp; int size;<br />
&nbsp; &nbsp; &nbsp; data = %CPPSELF.%FUNCTION_NAME(%1, <span style="color: #ddbb00;">&amp;size);</span><br />
&nbsp; &nbsp; &nbsp; if (data) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = PyTuple_New(size);<br />
&nbsp; &nbsp; &nbsp; &nbsp; PyObject* uni = 0;<br />
&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i <span style="color: #009900;">&lt; size; ++i<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uni = PyUnicode_DecodeUTF8<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>const char*<span style="color: #66cc66;">&#41;</span>data<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>,</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strlen<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>const char*<span style="color: #66cc66;">&#41;</span>data<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>,</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;strict&quot;</span><span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PyTuple_SetItem<span style="color: #66cc66;">&#40;</span>%PYARG_0, i, uni<span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#125;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;for <span style="color: #66cc66;">&#40;</span>int i = 0; i &lt; size; ++i<span style="color: #66cc66;">&#41;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;free<span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;free<span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#125;</span> else <span style="color: #66cc66;">&#123;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;Py_INCREF<span style="color: #66cc66;">&#40;</span>Py_None<span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;%PYARG_0 = Py_None;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#125;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; ...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h2>Baixando, compilando, etc.</h2>
<p>Chega de explicações, agora vamos experimentar o código. Lembre-se que precisará também dos arquivos de desenvolvimento que mencionei muito tempo atrás</p>
<p>Clone a versão mais recente do repositório git:</p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>setanta<span style="color: #000000; font-weight: bold;">/</span>python-epub.git</div></div>
<p>ou baixe o tarball: <a href="http://setantas.net/files/python-epub.tar.bz2">python-epub.tar.bz2</a></p>
<p>No diretório do código fonte crie um diretório <code class="codecolorer bash default"><span class="bash">build</span></code> e&#8230;</p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">cd</span> python-epub<br />
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> build<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> build<br />
cmake ..<br />
<span style="color: #c20cb9; font-weight: bold;">make</span><br />
ctest</div></div>
<p>O último comando merece uma conversa à respeito.</p>
<h3>Testar, Testar, Testar</h3>
<p>Quando trabalhando com desenvolvimento de bindings há uma miríade de coisas que podem dar errado, e muitas delas dão errado em completo silêncio. Tendo isto em mente, eu digo-lhe que ter testes de unidade torna a vida do desenvolvedor de bindings suportável.</p>
<p>Veja o <a href="https://github.com/setanta/python-epub/tree/master/tests">diretório de testes</a> para exemplos de como usar o bingind python-epub.</p>
<p>Para resultados detalhados dos testes, rode ctest com a opção <code class="codecolorer bash default"><span class="bash"><span style="color: #660033;">-V</span></span></code> (verboso).</p>
<h2>Exemplo de UI (senão seria tedioso)</h2>
<p>Mas a própria UI é bem tediosa, embora feita com o espetacular <a href="http://www.pyside.org">PySide</a>, ela nem sequer mostra imagens. Por outro lado, com um pouco de código agora posso ver o conteúdo de um ebook ePub.</p>
<p>De dentro do diretório <code class="codecolorer bash default"><span class="bash">python-epub<span style="color: #000000; font-weight: bold;">/</span>build</span></code> chame o visualizador de ePub dessa forma:</p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">python ..<span style="color: #000000; font-weight: bold;">/</span>simple-ui<span style="color: #000000; font-weight: bold;">/</span>bookviewer.py ..<span style="color: #000000; font-weight: bold;">/</span>tests<span style="color: #000000; font-weight: bold;">/</span>beyond-the-wall-of-sleep.epub</div></div>
<p>Ele sempre espera um parâmetro com o caminho para um arquivo ePub, neste caso <a href="http://www.feedbooks.com/book/237/beyond-the-wall-of-sleep">&#8220;Beyond the Wall of Sleep&#8221;</a> de <a href="http://www.feedbooks.com/author/12">Lovecraft</a>.</p>
<p>Screenshots:</p>
<p><img src="http://www.setantas.net/blog/wp-content/uploads/2011/03/epubviewer_screenshots.png" alt="Simplest ePub viewer (made with PySide)" width="580" height="480" class="size-full wp-image-516" /></p>
<p><map name='google_ad_map_517_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/517?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_517_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=517&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2011%2F03%2F09%2Fpython-bindings-para-libepub-usando-shiboken%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2011/03/09/python-bindings-para-libepub-usando-shiboken/&via=&text=Python bindings para libepub usando Shiboken&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2011/03/09/python-bindings-para-libepub-usando-shiboken/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python bindings for libepub using Shiboken</title>
		<link>http://www.setantas.net/blog/2011/03/08/python-bindings-for-libepub-using-shiboken/</link>
		<comments>http://www.setantas.net/blog/2011/03/08/python-bindings-for-libepub-using-shiboken/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 00:31:54 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[pro]]></category>
		<category><![CDATA[bindings]]></category>
		<category><![CDATA[ebooks]]></category>
		<category><![CDATA[ePub]]></category>
		<category><![CDATA[PySide]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Shiboken]]></category>

		<guid isPermaLink="false">http://www.setantas.net/blog/?p=512</guid>
		<description><![CDATA[I have a Kindle, I like it very much, but unfortunately I can&#8217;t say the same about the format it used for books. Not that I have made a detailed study of the mobi format and came to the conclusion that it is technically inferior. No. The problem is that ePub is so much more [...]]]></description>
			<content:encoded><![CDATA[<p>I have a <a href="http://twitpic.com/3ucxtj">Kindle</a>, I like it very much, but unfortunately I can&#8217;t say the same about the format it used for books. Not that I have made a detailed study of the mobi format and came to the conclusion that it is technically inferior. No. The problem is that <a title="Wikipedia: ePub" href="http://en.wikipedia.org/wiki/EPUB">ePub</a> is so much more popular, which mean more books, and more tools to play with. <a href="http://calibre-ebook.com/">Calibre</a> is awesome to convert between eBook formats, but I prefer the simplicity of downloading a book, copying it to the device and reading right away.</p>
<p>When my Kindle is not at hand, my replacement reader is a N900 with <a title="eBook reader for Maemo 5" href="http://juhanagsoc.wordpress.com/">MeBook</a>, one of my favorite apps &#8211; it looks for books (in ePub format) on <a title="Feedbooks" href="http://www.feedbooks.com/">Feedbooks</a>, downloads to device and show them in a nice list with covers and all. Looking at MeBook source code I learned that it uses <a title="eBook tools" href="http://sourceforge.net/projects/ebook-tools/">libepub</a> to read the ePub eBooks, so I thought it would be interesting to make a Python binding to <strong>libepub</strong>. And here we are.</p>
<p>Ah, and one more thing before we start, I found a related Python project on github called <a href="https://github.com/jharjono/libepub">libepub</a>. Hadn&#8217;t checked it yet, but I mention it here for information&#8217;s sake.</p>
<h2>Shiboken</h2>
<p><a title="Shiboken" href="http://www.setantas.net/blog/2009/08/31/shiboken/" target="_self">Shiboken</a> is the world famous tool used to generate the world famous <a title="PySide" href="http://pyside.org">PySide</a> bindings (that happen to have reached <a title="PySide: Python for Qt 1.0 released!" href="http://www.pyside.org/2011/03/pyside-python-for-qt-1-0-released/">1.0</a> last week &#8211; yay!) It is one of the best tools around to generate Python bindings for C++ libraries. But that&#8217;s me talking &#8211; I work on it. But <strong>libepub</strong> is written in C, and even though Shiboken can generate bindings for a bunch of global functions and put them together in a Python module, that&#8217;s crappy. So I&#8217;ll have to make some preparations to make <strong>libepub</strong> appear beautiful in Python.</p>
<blockquote><p><strong>Pre-requisites:</strong> development files (i.e. the headers) for <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">ApiExtractor</a>, <a title="GeneratorRunner 0.6" href="http://pyside.org/docs/generatorrunner/">GeneratorRunner</a>, <a title="Shiboken" href="http://pyside.org/docs/shiboken/">Shiboken</a>, and <strong>libepub</strong>. (For Debian/Ubuntu users this means: <strong>libapiextractor-dev</strong>, <strong>libgenrunner-dev</strong>, <strong>libshiboken-dev</strong>, and <strong>libepub-dev</strong>.) And the C++ compiler plus CMake, of course.</p></blockquote>
<p><strong>Remainder:</strong> ApiExtractor, GeneratorRunner and Shiboken are made with Qt (only the core libs, no ui for them), but the bindings generated do not depend on Qt at all. Except, obviously, if the library being wrapped already does.</p>
<h3>libepub</h3>
<p>First let&#8217;s have an overview of <strong>libepub</strong>. It has three structures used as opaque pointers:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// Contains information about the ePub file.</span><br />
<span style="color: #0000ff;">struct</span> epub<span style="color: #008080;">;</span><br />
<span style="color: #666666;">// Iterator object for the Table of Contents.</span><br />
<span style="color: #0000ff;">struct</span> titerator<span style="color: #008080;">;</span><br />
<span style="color: #666666;">// Iterator object for the book contents.</span><br />
<span style="color: #0000ff;">struct</span> eiterator<span style="color: #008080;">;</span></div></div>
<p>If you want to read the contents of an ePub file, call the function that will create an epub structure, iterate through its table of contents with a titerator, and then the contents themselves with an eiterator.</p>
<p>Most functions follow that &#8220;object oriented C&#8221; format seen in other libraries, with the first argument being a pointer to the structure that represents the <em>&#8220;this&#8221;</em> or <em>&#8220;self&#8221;</em> in OO languages. Examples:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">void</span><br />
epub_dump<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> epub<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span><br />
epub_get_metadata<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> epub,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">enum</span> epub_metadata type,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">int</span><br />
epub_get_data<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> epub,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> name,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></div>
<h3>CMake</h3>
<p>I&#8217;ll use CMake as the build system for the bindings because I feel comfortable with it &#8211; it is the same used in PySide and all the Shiboken generator tool chain. I&#8217;ll not give too much attention to this part of the process, just check the <strong>CMakeLists.txt</strong> files; more detailed explanation on the process of building a binding can be found in the <a title="PySide Binding Generation Tutorial" href="http://developer.qt.nokia.com/wiki/Category:LanguageBindings::PySide::Shiboken::PySide_Binding_Generation_Tutorial">PySide Binding Generation Tutorial</a>. For really really basic information check <a title="PySide CMake Primer" href="http://developer.qt.nokia.com/wiki/PySide_CMake_Primer">PySide CMake Primer</a>.</p>
<h2>Handmade C++ Wrapper for a C library</h2>
<p>To generate Python bindings for a C++ library one must write a XML description called type system, which will declare what must be exposed on Python land, and if any of this needs modification: global functions, classes, namespaces, enums. For example, if in C++ I have the class <code class="codecolorer cpp default"><span class="cpp">Rectangle</span></code>, I would declare it in the type system this way:</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'Rectangle'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>All the methods belonging to <code class="codecolorer cpp default"><span class="cpp">Rectangle</span></code> would be exposed to Python automatically. The same is not true for the C functions that representing the methods for the epub struct. Unfortunately there&#8217;s no way to tell the Shiboken generator that I want to have the epub structure and functions represented as a class with methods, so we have to make a thin C++ wrapper around the C structures. That would be a lot of work for a huge C library, but even with a tiny one I feel uncomfortable having to resort for this kind of hackery. The type system should be expressive enough to bind C structs and functions as if they were proper objects with methods. I&#8217;ll mark this for future community/out-of-work improvements on Shiboken.</p>
<p>Let&#8217;s see a snippet from <a title="epub_cpp_wrappers.h @ 757d8dc" href="https://github.com/setanta/python-epub/blob/757d8dcd34943dd71495959a81fb15ce07896898/epub_cpp_wrappers.h">epub_cpp_wrapper.h</a>:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> EPub <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; ...<br />
<br />
&nbsp; &nbsp; ~EPub<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> epub_close<span style="color: #008000;">&#40;</span>m_epub<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">inline</span> EPub<span style="color: #000040;">*</span><br />
&nbsp; &nbsp; open<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> filename, <span style="color: #0000ff;">int</span> debug <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> book <span style="color: #000080;">=</span> epub_open<span style="color: #008000;">&#40;</span>filename, debug<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>book<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">new</span> EPub<span style="color: #008000;">&#40;</span>book<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">void</span> dump<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> epub_dump<span style="color: #008000;">&#40;</span>m_epub<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">int</span><br />
&nbsp; &nbsp; get_data<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> name, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> data<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_get_data<span style="color: #008000;">&#40;</span>m_epub, name, data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; ...<br />
<br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> EPub<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> ptr<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> m_epub<span style="color: #008000;">&#40;</span>ptr<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; EPub<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EPub<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> other<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; EPub<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EPub<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> other<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">struct</span> epub<span style="color: #000040;">*</span> m_epub<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>Notice that all methods were marked as <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">inline</span></span></code> to make this wrapper as thinner as possible. (GCC, I&#8217;m looking at you!)</p>
<h3>Epub::open</h3>
<p>The <code class="codecolorer cpp default"><span class="cpp">epub_open</span></code> function becomes the static method <code class="codecolorer cpp default"><span class="cpp">EPub<span style="color: #008080;">::</span><span style="color: #007788;">open</span></span></code> that will return a new <code class="codecolorer cpp default"><span class="cpp">EPub</span></code> object for the ePub file given by <code class="codecolorer cpp default"><span class="cpp">filename</span></code> parameter, or a null pointer if the file is invalid or doesn&#8217;t exist.<br />
The constructor for this class was made private so the only way to create EPub objects is via <code class="codecolorer cpp default"><span class="cpp">EPub<span style="color: #008080;">::</span><span style="color: #007788;">open</span></span></code>, that&#8217;ll never create an invalid <code class="codecolorer cpp default"><span class="cpp">EPub</span></code>.</p>
<h3>~Epub</h3>
<p>In C the responsible for freeing the epub structure is <strong>epub_close</strong>, but I&#8217;ll not make it <code class="codecolorer cpp default"><span class="cpp">EPub<span style="color: #008080;">::</span><span style="color: #007788;">close</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> because the C++ equivalent for it is the class&#8217; destructor.</p>
<p>A generated Python binding for what we have until now would look roughly like this:</p>
<div class="codecolorer-container python geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> epub<br />
book = epub.<span style="color: black;">EPub</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sample.epub'</span><span style="color: black;">&#41;</span><br />
title = book.<span style="color: black;">get_metadata</span><span style="color: black;">&#40;</span>epub.<span style="color: black;">EPUB_TITLE</span><span style="color: black;">&#41;</span></div></div>
<p>Of course I didn&#8217;t explained how this would be generated, that the module would be called <code class="codecolorer python default"><span class="python">epub</span></code>, what is <code class="codecolorer python default"><span class="python">epub.<span style="color: black;">EPUB_TITLE</span></span></code>, and how Python would know what to do with <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span></span></code>, but bear with me.</p>
<h3>Moving enums around</h3>
<p><code class="codecolorer cpp default"><span class="cpp">EPUB_TITLE</span></code> is a value from the <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code> enum, if exposed to Python as they are, they&#8217;ll look like this:</p>
<div class="codecolorer-container python geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> epub<br />
epub.<span style="color: black;">epub_metadata</span><br />
epub.<span style="color: black;">EPUB_TITLE</span></div></div>
<p>Which is pretty ugly and lame. Since <strong>epub_metadata</strong> is an enum related to the epub object (as the <strong>epub_</strong> prefix tells us), it would be natural that it was moved inside the EPub class. In my fantasy world, the type system tag that describes a C++ enum to Python would have the option to move it inside another object, and also to be renamed. Something along these lines:</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enum-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'epub_metadata'</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">rename</span>=<span style="color: #ff0000;">'metatada'</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">move-into</span>=<span style="color: #ff0000;">'EPub'</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">remove-enum-value-prefix</span>=<span style="color: #ff0000;">'EPUB_'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>And here I have another thing for a Shiboken TODO list. While this feature is not implemented, I&#8217;ll have to do it manually.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> EPub <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">enum</span> metadata <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ID <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_ID<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; TITLE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_TITLE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; CREATOR <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_CREATOR<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; CONTRIB <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_CONTRIB<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; SUBJECT <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_SUBJECT<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; PUBLISHER <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_PUBLISHER<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; DESCRIPTION <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_DESCRIPTION<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; DATE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_DATE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; TYPE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_TYPE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; FORMAT <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_FORMAT<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; SOURCE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_SOURCE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; LANG <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_LANG<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; RELATION <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_RELATION<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; COVERAGE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_COVERAGE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; RIGHTS <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_RIGHTS<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; META <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>EPUB_META<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span><br />
&nbsp; &nbsp; get_metadata<span style="color: #008000;">&#40;</span>metadata type, <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_get_metadata<span style="color: #008000;">&#40;</span>m_epub,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;epub_metadata<span style="color: #008000;">&#40;</span>type<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>The <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code> enum values were cast to <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">int</span></span></code> to prevent the <strong>ApiExtractor</strong> to emitting a bunch of warnings saying that it cannot tell who these guys are.</p>
<p>Anyways, it&#8217;s so awful&#8230; to have a fancy generator, and having to write all this&#8230; noooo!</p>
<h3>TIterator and EIterator</h3>
<p>The C structures <code class="codecolorer cpp default"><span class="cpp">titerator</span></code> and <code class="codecolorer cpp default"><span class="cpp">eiterator</span></code> will be wrapped by the C++ classes <code class="codecolorer cpp default"><span class="cpp">TIterator</span></code> and <code class="codecolorer cpp default"><span class="cpp">EIterator</span></code>, respectively, and like the <code class="codecolorer cpp default"><span class="cpp">EPub</span></code> class their constructors are private.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> TIterator <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">enum</span> type <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; NAVMAP <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>TITERATOR_NAVMAP<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; GUIDE <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>TITERATOR_GUIDE<span style="color: #008000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; PAGES <span style="color: #000080;">=</span> <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span>TITERATOR_PAGES<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; ~TIterator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> epub_free_titerator<span style="color: #008000;">&#40;</span>m_iter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> isValid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_tit_curr_valid<span style="color: #008000;">&#40;</span>m_iter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">friend</span> <span style="color: #0000ff;">class</span> EPub<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> TIterator<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> iter<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">:</span> m_iter<span style="color: #008000;">&#40;</span>iter<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> m_iter<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>New instances of <code class="codecolorer cpp default"><span class="cpp">TIterator</span></code> and <code class="codecolorer cpp default"><span class="cpp">EIterator</span></code> are created by <code class="codecolorer cpp default"><span class="cpp">EPub</span></code> methods, because of that it must be a <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">friend</span></span></code> of the iterator classes.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> EPub <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> EIterator<span style="color: #000040;">*</span><br />
&nbsp; &nbsp; get_iterator<span style="color: #008000;">&#40;</span>EIterator<span style="color: #008080;">::</span><span style="color: #007788;">type</span> type, <span style="color: #0000ff;">int</span> opt <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">struct</span> eiterator<span style="color: #000040;">*</span> it <span style="color: #000080;">=</span> epub_get_iterator<span style="color: #008000;">&#40;</span>m_epub, eiterator_type<span style="color: #008000;">&#40;</span>type<span style="color: #008000;">&#41;</span>, opt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">new</span> EIterator<span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> TIterator<span style="color: #000040;">*</span><br />
&nbsp; &nbsp; get_titerator<span style="color: #008000;">&#40;</span>TIterator<span style="color: #008080;">::</span><span style="color: #007788;">type</span> type, <span style="color: #0000ff;">int</span> opt <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> it <span style="color: #000080;">=</span> epub_get_titerator<span style="color: #008000;">&#40;</span>m_epub, titerator_type<span style="color: #008000;">&#40;</span>type<span style="color: #008000;">&#41;</span>, opt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">new</span> TIterator<span style="color: #008000;">&#40;</span>it<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<h2>python-epub</h2>
<p>Now it&#8217;s time to say to the generator which goes in and which must change in the bindings.</p>
<h3>The global header</h3>
<p>The global header is a file that includes all other headers of the library that will be analyzed. In the global header the binding developer may also add some tweaks, like a <code class="codecolorer cpp default"><span class="cpp"><span style="color: #339900;">#define</span></span></code> that will trigger some condition in the target library headers, that will affect the generated binding.</p>
<p>The <a href="https://github.com/setanta/python-epub/blob/master/epub_global.h">epub_global.h</a> that I use here is very simple:</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#ifndef EPUB_GLOBAL_H</span><br />
<span style="color: #339900;">#define EPUB_GLOBAL_H</span><br />
<br />
<span style="color: #339900;">#include &amp;lt;epub.h&amp;gt;</span><br />
<span style="color: #339900;">#include &amp;lt;epub_shared.h&amp;gt;</span><br />
<span style="color: #339900;">#include &amp;lt;epub_version.h&amp;gt;</span><br />
<br />
<span style="color: #339900;">#include &quot;epub_cpp_wrappers.h&quot;</span><br />
<br />
<span style="color: #666666;">// ApiExtractor complains if it finds only pre-definitions.</span><br />
<span style="color: #0000ff;">struct</span> titerator <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">struct</span> eiterator <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #339900;">#endif</span></div></div>
<p>As the commentary tells us, ApiExtractor doesn&#8217;t like when it finds forward declarations without definitions. I choose to add these two bogus definitions for <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> titerator</span></code> and <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> eiterator</span></code>. (For some reason the generator said nothing about <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> epub</span></code>.) Other option would be not to add those bogus definitions, but add a line to the type system file telling the generator to ignore warnings relative to those structures.</p>
<h3>The Type System description</h3>
<p>Here follows a snippet from <a title="typesystem_epub.xml @ 78de928" href="https://github.com/setanta/python-epub/blob/78de92867f668d92a7610515eaeebe34487ebf03/typesystem_epub.xml">typesystem_epub.xml</a>.</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;typesystem</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">'epub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rejection</span> <span style="color: #000066;">enum-name</span>=<span style="color: #ff0000;">'epub_metadata'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'EPub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enum-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'metadata'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/typesystem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>The <code class="codecolorer cpp default"><span class="cpp">epub_metadata</span></code> enum is not exported to Python (at least not as it is) and to avoid the generator emitting his warnings, it must be explicitly rejected; its C++ substitute is added afterwards inside the EPub object type. The same happens to the other enums.</p>
<p>In the type system notation <code class="codecolorer xml default"><span class="xml">object-type</span></code> refers to objects that are passed around solely as pointers (like <code class="codecolorer cpp default"><span class="cpp">EPub</span></code>, whose copy constructor and operator are private). If, otherwise, the object can be passed as value, it should be declared as an <code class="codecolorer xml default"><span class="xml">value-type</span></code>, as our <code class="codecolorer cpp default"><span class="cpp">Rectangle</span></code> example mentioned before.</p>
<h3>Python&#8217;s Iterator Protocol</h3>
<p>In Python, if an object supports the <a href="http://docs.python.org/library/stdtypes.html#iterator-types">Iterator Protocol</a> I can use it on <code class="codecolorer python default"><span class="python"><span style="color: #ff7700;font-weight:bold;">for</span></span></code> statements, like this:</p>
<div class="codecolorer-container python geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> epub <span style="color: #ff7700;font-weight:bold;">import</span> EPub, TIterator<br />
book = EPub.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">epub_file</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">for</span> toc_it <span style="color: #ff7700;font-weight:bold;">in</span> book.<span style="color: black;">get_titerator</span><span style="color: black;">&#40;</span>TIterator.<span style="color: black;">NAVMAP</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> toc_it.<span style="color: black;">isValid</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">continue</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'link : '</span> + toc_it.<span style="color: black;">link</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'label: '</span> + toc_it.<span style="color: black;">label</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>Following the Python Iterator Protocol consists solely of an object implementing the methods <code class="codecolorer python default"><span class="python"><span style="color: #0000cd;">__iter__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code> and <code class="codecolorer python default"><span class="python">__next__<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>.</p>
<blockquote><p><strong>Note:</strong> the correct name for the method is <code class="codecolorer python default"><span class="python">next<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code> and not <code class="codecolorer python default"><span class="python">__next__<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>. That&#39;s a minor bug in the generator that I just found.
</p></blockquote>
<p>The XML to add iterator protocol features into <code class="codecolorer text default"><span class="text">TIterator</span></code> class will be lengthy, so I&#39;ll split it into two parts, the first dealing with <a href="http://www.pyside.org/docs/apiextractor/typesystem_templates.html">type system code templates</a>.</p>
<h4>Type System templates</h4>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;typesystem</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">'epub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__iter__'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_INCREF(%PYSELF);<br />
&nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = %PYSELF;<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/template<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__next__'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; if (%CPPSELF.next()) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__iter__'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; } else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PyErr_SetNone(PyExc_StopIteration);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/template<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; ...</div></div>
<p>The iterator methods for <code class="codecolorer python default"><span class="python">TIterator</span></code> and <code class="codecolorer python default"><span class="python">EIterator</span></code> have exactly the same implementation, so it&#8217;ll be smart to use type system <a href="http://www.pyside.org/docs/apiextractor/typesystem_templates.html">templates</a> and have the code, and its eventual bugs, in a single place.</p>
<p><code class="codecolorer python default"><span class="python">iterator.<span style="color: #0000cd;">__iter__</span></span></code> method just need to return the object itself with its reference counter incremented by one. <code class="codecolorer python default"><span class="python">iterator.__next__</span></code> calls the underlying C++ object&#8217;s <code class="codecolorer cpp default"><span class="cpp">next<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> (it also returns itself, and increments the refcounter), and raises a Python <code class="codecolorer python default"><span class="python"><span style="color: #008000;">StopIteration</span></span></code> exception when it reaches the end.</p>
<p>The <a href="http://www.pyside.org/docs/shiboken/typesystemvariables.html">type system variables</a> <code class="codecolorer xml default"><span class="xml">%PYSELF</span></code>, <code class="codecolorer xml default"><span class="xml">%PYARG_0</span></code> and <code class="codecolorer xml default"><span class="xml">%CPPSELF</span></code> are replaced by values dependent on the context where they are used (e.g. <code class="codecolorer python default"><span class="python">TIterator</span></code> or <code class="codecolorer python default"><span class="python">EIteration</span></code> classes). Check the <a href="http://www.pyside.org/docs/shiboken/typesystemvariables.html">documentation</a> for their meaning·</p>
<h4>Adding the iterator methods</h4>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'TIterator'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'next()'</span> <span style="color: #000066;">remove</span>=<span style="color: #ff0000;">'all'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'__iter__'</span> <span style="color: #000066;">return-type</span>=<span style="color: #ff0000;">'PyObject*'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__iter__'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/add-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'__next__'</span> <span style="color: #000066;">return-type</span>=<span style="color: #ff0000;">'PyObject*'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'iterator.__next__'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/add-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/typesystem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>First the original C++ <code class="codecolorer cpp default"><span class="cpp">next<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> is removed, then the ones for the Python iterator protocol are added, using <code class="codecolorer xml default"><span class="xml"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></span></code> tag to insert the previously defined custom code. Exactly the same lines will be added to <code class="codecolorer python default"><span class="python">EIterator</span></code> class.</p>
<h4>Just one more bit of hackery</h4>
<p>Only one obstacle remains on the way of having proper Python iterators. When Python&#8217;s <code class="codecolorer python default"><span class="python"><span style="color: #ff7700;font-weight:bold;">for</span></span></code> statement is used to iterate through an iterable object, in the first round it calls the object&#8217;s <code class="codecolorer python default"><span class="python"><span style="color: #0000cd;">__iter__</span></span></code> method, and immediately after it calls <code class="codecolorer python default"><span class="python">next</span></code>, and keeps calling <code class="codecolorer python default"><span class="python">next</span></code> for each new iteration.</p>
<p>The problem here is that our underlying C iterator returns an object loaded with proper content when <code class="codecolorer python default"><span class="python"><span style="color: #0000cd;">__iter__</span></span></code> is called, then the way that Python&#8217;s <code class="codecolorer python default"><span class="python"><span style="color: #ff7700;font-weight:bold;">for</span></span></code> iteration works will cause the first item to be bypassed. A workaround for this case is to use a flag on the C++ wrapper that checks if the iterator has just been created, so that it will not move forward when <code class="codecolorer python default"><span class="python">next</span></code> is called on it for the first time.</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">class</span> TIterator <span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> next<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_isFirst<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m_isFirst <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">return</span> epub_tit_next<span style="color: #008000;">&#40;</span>m_iter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">friend</span> <span style="color: #0000ff;">class</span> EPub<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">explicit</span> TIterator<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> iter<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">:</span> m_iter<span style="color: #008000;">&#40;</span>iter<span style="color: #008000;">&#41;</span>, m_isFirst<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">struct</span> titerator<span style="color: #000040;">*</span> m_iter<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">bool</span> m_isFirst<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></div>
<p>I had this freedom because <code class="codecolorer cpp default"><span class="cpp">TIterator</span></code> is a class completely under my (me, the binding developer) control. If <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">struct</span> titerator</span></code> were a C++ class from the beginning that approach would not be the best. Perhaps <strong>libshiboken</strong> (the supporting library used by all Shiboken generated bindings) should provide a base iterator class to handle this particular difference between Python and C++ iterators. Or perhaps the generated class, when identified as an iterable by the presence of iterator protocol methods added by the binding developer, should have such provisions. The latter options seems best, and that&#8217;s one more item for my list of future improvements.</p>
<h3>Custom Conversions</h3>
<h4>Returning unicode values</h4>
<p>The <code class="codecolorer cpp default"><span class="cpp">EIterator<span style="color: #008080;">::</span><span style="color: #007788;">curr</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> methods <code class="codecolorer cpp default"><span class="cpp">EIterator<span style="color: #008080;">::</span><span style="color: #007788;">curr_url</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></span></code> returns values of <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span></span></code> type, which doesn&#8217;t have a converter (<code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span></span></code> does have), so I&#8217;ve written a custom piece of code to convert it to Python&#8217;s unicode.</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;typesystem</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">'epub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'return_char_pointer'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; char* %0 = %CPPSELF.%FUNCTION_NAME();<br />
&nbsp; &nbsp; &nbsp; &nbsp; if (%0) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = PyUnicode_DecodeUTF8(%0, strlen(%0), &quot;strict&quot;);<br />
&nbsp; &nbsp; &nbsp; &nbsp; } else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Py_INCREF(Py_None);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = Py_None;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/template<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'EIterator'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'curr()'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'return_char_pointer'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'curr_url()'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">'beginning'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;insert-template</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'return_char_pointer'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/typesystem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h4>Modifying a method&#8217;s signature</h4>
<p>Some C++ method signatures couldn&#8217;t automatically be converted to meaningful Python code, so I added more custom code to handle the situation on a case by case basis. For example, the method</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span><br />
EPub<span style="color: #008080;">::</span><span style="color: #007788;">get_metadata</span><span style="color: #008000;">&#40;</span>metadata type, <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></div>
<p>The <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> size</span></code> argument receives a pointer to an int, which will contain the size of the list of unicode strings returned as <code class="codecolorer cpp default"><span class="cpp"><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span></span></code>. In Python it would merely return a list of unicode objects, and the call to <code class="codecolorer cpp default"><span class="cpp">get_metadata</span></code> doesn&#8217;t need the <code class="codecolorer cpp default"><span class="cpp">size</span></code> argument.</p>
<p>I believe the type system description is enough to see how the modification system works.</p>
<div class="codecolorer-container xml geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'EPub'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enum-type</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">'metadata'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-function</span> <span style="color: #000066;">signature</span>=<span style="color: #ff0000;">'get_metadata(EPub::metadata,int*)'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-argument</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">'2'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;remove-argument</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-argument<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modify-argument</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">'return'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;replace-type</span> <span style="color: #000066;">modified-type</span>=<span style="color: #ff0000;">'PyTuple'</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-argument<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inject-code</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">'target'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; unsigned char** data = 0;<br />
&nbsp; &nbsp; &nbsp; int size;<br />
&nbsp; &nbsp; &nbsp; data = %CPPSELF.%FUNCTION_NAME(%1, <span style="color: #ddbb00;">&amp;size);</span><br />
&nbsp; &nbsp; &nbsp; if (data) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; %PYARG_0 = PyTuple_New(size);<br />
&nbsp; &nbsp; &nbsp; &nbsp; PyObject* uni = 0;<br />
&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i <span style="color: #009900;">&lt; size; ++i<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uni = PyUnicode_DecodeUTF8<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>const char*<span style="color: #66cc66;">&#41;</span>data<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>,</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strlen<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>const char*<span style="color: #66cc66;">&#41;</span>data<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>,</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;strict&quot;</span><span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PyTuple_SetItem<span style="color: #66cc66;">&#40;</span>%PYARG_0, i, uni<span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#125;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;for <span style="color: #66cc66;">&#40;</span>int i = 0; i &lt; size; ++i<span style="color: #66cc66;">&#41;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;free<span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;free<span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#125;</span> else <span style="color: #66cc66;">&#123;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;Py_INCREF<span style="color: #66cc66;">&#40;</span>Py_None<span style="color: #66cc66;">&#41;</span>;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;%PYARG_0 = Py_None;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#125;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">&lt;/inject-code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modify-function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; ...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h2>Downloading, building, etc.</h2>
<p>Enough with the explanations, now let&#8217;s try the code. Remember that you&#8217;ll need also development files that I mentioned long time ago.</p>
<p>Clone the latest version from the git repository:</p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>setanta<span style="color: #000000; font-weight: bold;">/</span>python-epub.git</div></div>
<p>or download the tarball: <a href="http://setantas.net/files/python-epub.tar.bz2">python-epub.tar.bz2</a></p>
<p>Inside the source code directory create a <code class="codecolorer bash default"><span class="bash">build</span></code> directory and &#8230;</p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">cd</span> python-epub<br />
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> build<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> build<br />
cmake ..<br />
<span style="color: #c20cb9; font-weight: bold;">make</span><br />
ctest</div></div>
<p>The last command deserves some talking about.</p>
<h3>Testing, Testing, Testing</h3>
<p>When working with binding development there&#8217;s a myriad of things that can go wrong, and a number of them go wrong in complete silence. With this in mind, I tell you that having unit tests makes the binding developer life bearable.</p>
<p>To see detailed results from the tests, run ctest with <code class="codecolorer bash default"><span class="bash"><span style="color: #660033;">-V</span></span></code> (verbose) option.</p>
<p>Check the <a href="https://github.com/setanta/python-epub/tree/master/tests">tests directory</a> for examples on how to use the python-epub bindings.</p>
<h2>UI Example (or else it would be boring)</h2>
<p>But the UI itself is very boring, although it was made with the amazing <a href="http://www.pyside.org">PySide</a> I did it as simple as possible, it doesn&#8217;t even show images. On the other hand, with very little code I can now see what&#8217;s inside an ePub ebook.</p>
<p>From <code class="codecolorer bash default"><span class="bash">python-epub<span style="color: #000000; font-weight: bold;">/</span>build</span></code> directory call the ePub viewer like this:</p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">python ..<span style="color: #000000; font-weight: bold;">/</span>simple-ui<span style="color: #000000; font-weight: bold;">/</span>bookviewer.py ..<span style="color: #000000; font-weight: bold;">/</span>tests<span style="color: #000000; font-weight: bold;">/</span>beyond-the-wall-of-sleep.epub</div></div>
<p>It always expects a parameter with the path to an ePub file, in this case <a href="http://www.feedbooks.com/book/237/beyond-the-wall-of-sleep">&#8220;Beyond the Wall of Sleep&#8221;</a> by <a href="http://www.feedbooks.com/author/12">Lovecraft</a>.</p>
<p>Screenshots:</p>
<p><img src="http://www.setantas.net/blog/wp-content/uploads/2011/03/epubviewer_screenshots.png" alt="Simplest ePub viewer (made with PySide)" width="580" height="480" class="size-full wp-image-516" /></p>
<p><map name='google_ad_map_512_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/512?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_512_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=512&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2011%2F03%2F08%2Fpython-bindings-for-libepub-using-shiboken%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2011/03/08/python-bindings-for-libepub-using-shiboken/&via=&text=Python bindings for libepub using Shiboken&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2011/03/08/python-bindings-for-libepub-using-shiboken/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tubarão</title>
		<link>http://www.setantas.net/blog/2010/07/19/tubarao/</link>
		<comments>http://www.setantas.net/blog/2010/07/19/tubarao/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 19:23:31 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[mine]]></category>
		<category><![CDATA[pt]]></category>

		<guid isPermaLink="false">http://www.setantas.net/blog/?p=478</guid>
		<description><![CDATA[Antigamente pensava que, embora goste muito dele, tinha pouco em comum com meu pai. Não estava completamente errado, mas esta estória não é sobre isso.
Fomos lá no hospital Santa Maria, na minha cidade, pra render o turno da minha mãe, que está acompanhando meu tio na internação.
O hospital fica uns duzentos metros da casa dos [...]]]></description>
			<content:encoded><![CDATA[<p>Antigamente pensava que, embora goste muito dele, tinha pouco em comum com meu pai. Não estava completamente errado, mas esta estória não é sobre isso.</p>
<p>Fomos lá no hospital Santa Maria, na minha cidade, pra render o turno da minha mãe, que está acompanhando meu tio na internação.<br />
O hospital fica uns duzentos metros da casa dos meus pais. Mais duzentos metros e temos a casa do tio, e com mais duzetos é o cemitério. Tudo é perto na minha cidade, pouca necessidade de carro ou ônibus.</p>
<p>Só pra localizar melhor as coisas, esse tio não é um tio genérico, ele criou minha mãe como pai, logo é como se fosse meu avô. Todos chamamos ele de Nêgo (com ê mesmo). Ele tomava conta do pequeno eu de 5 anos (acho) enquanto minha mãe analisava amostras de sangue no laboratório. Mas meu tio também tinha seus compromissos de sacristão de uma paróquia, pra onde ele me levava. Lembro de ir pra uma extrema unção (ou era um velório?) onde fiquei cantando com o folhetinho virado de cabeça pra baixo.</p>
<p>Chegando na enfermaria do hospital mandamos minha mãe jantar. Eu tinha a intenção de entreter o doente, mas ele estava com a voz bem fraquinha pra conversar. Melhor uma estória. Então fiz a pergunta mágica ao meu pai sobre como vovô aprendeu a nadar tão bem vivendo num sítio no interior de Pernambuco.</p>
<p><a href="http://www.setantas.net/blog/wp-content/uploads/2010/07/Fernando_de_Noronha_-_dois_Irmãos_-_praia_do_sancho.jpg"><img class="aligncenter size-medium wp-image-479" title="Fernando de Noronha" src="http://www.setantas.net/blog/wp-content/uploads/2010/07/Fernando_de_Noronha_-_dois_Irmãos_-_praia_do_sancho-300x224.jpg" alt="Fernando de Noronha" width="300" height="224" /></a></p>
<p>Então, era uma vez meu bisavô, que não sei o nome, por causa de quem começa tudo. Tem essa estória vaga e difusa de que ele matou duas pessoas, em duas situações distintas, com tiros à queima roupa de seu perverso bacamarte. Me foi contado que ele socava vidro e pregos junto com a pólvora. Um dos tiros teria arrancado o coração de uma mulher e o outro a cabeça de um sujeito. Mas pode ter sido o oposto. A causa de tanta raiva pode ter sido fofoca e ciúme. Ele tinha uma amante e estavam contando pra minha bisavó. Meu bisavô, amante da paz que era tentou resolver do jeito dele. Contudo, nada é preciso nessa estória. Essas lendas de família são assim mesmo.</p>
<p>Fato é que nos idos de mil novecentos e dez e poucos os bandidos perigosos iam para&#8230;  O que é que ele vai ganhar Lombardi? Uma viagem com tudo pago pra Fernando de Noronha, Silvio! E a estranheza só aumenta, meu pai contou que a família do condenado ia junto com ele, mas ficavam numa casa de verdade na ilha, e o meliante só precisava dormir na cela com provável vista pro mar. E essa era vida do meu bisavô, dormir no xilindró e fazer mais filhos durante o dia. Penso que ele só fazia pela diversão, mas cada filho nascido na ilha diminuia sua pena.</p>
<p>E foi assim que meu avô aprendeu a nadar, praticando dos 13 aos 18 em Fernando de Noronha, enquanto o pai cumpria pena por crimes hediondos.</p>
<p>Sabia desse conto só até essa parte, mas o mais legal de ouvir meu pai narrando tudo de novo é que sempre posso confiar na ampliação da estória com um detalhe que lembrou na hora. O detalhe dessa vez foi um tubarão.</p>
<p><a href="http://www.setantas.net/blog/wp-content/uploads/2010/07/ShagEyeShark.jpg"><img class="aligncenter size-medium wp-image-480" title="Tubarão" src="http://www.setantas.net/blog/wp-content/uploads/2010/07/ShagEyeShark-300x179.jpg" alt="Tubarão" width="300" height="179" /></a></p>
<p>Estavam pescando numa jangada lá no mar azul de Fernando de Noronha meu avô e seu irmão. Pescavam com anzol grande e corda resistente, esperando pegar algo graúdo. Pois foi um tubarão que veio, não sei a espécie, só sei que era do tipo com dentes afiados e do tamanho da jangada onde cabem duas pessoas.</p>
<p>Eles lutaram com o peixão por um bom tempo, até que o bicho virou o barquinho. Nessa parte da narrativa eu só acreditei que meu avô saiu vivo porque estavam o filho e o neto conversando sobre ele. Assisti muitos filmes de tubarão pra saber que o objetivo da espécie, em todas suas variantes, é o extermínio da raça humana. Veja o tubarão baleia por exemplo, aquele jeitão simpático dele, aquela boca de garagem de fusca, isso é só pra baixar nossa guarda.</p>
<p>Na vida real o tubarão com um gancho na boca só quer fugir. Vovô e seu irmão com suas inseparáveis facas (sim, os filhos do condenado andavam por aí com facas &#8211; eram aqueles tempos que todo mundo fala de amarrar cachorro com salsicha) só queriam um almoço de frutos do mar.</p>
<p>Bem, voltando, vovô conseguiu furar o tubarão e logo o bicho enfraquecia. Eles desviraram a jangada e jogaram o peixão no meio. Os pescadores adultos festejaram a habilidade e ousadia dos meus antepassados adolescentes e todos fizeram um feliz churrasco de tubarão.</p>
<p>Essas horas minha mãe já voltou e tenho um ônibus pra pegar.</p>
<p><map name='google_ad_map_478_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/478?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_478_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=478&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2010%2F07%2F19%2Ftubarao%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2010/07/19/tubarao/&via=&text=Tubarão&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2010/07/19/tubarao/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Viva Las Vegas!</title>
		<link>http://www.setantas.net/blog/2009/09/22/viva-las-vegas/</link>
		<comments>http://www.setantas.net/blog/2009/09/22/viva-las-vegas/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 04:30:17 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[mine]]></category>
		<category><![CDATA[pt]]></category>
		<category><![CDATA[Estórias]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/2009/09/22/viva-las-vegas/</guid>
		<description><![CDATA[Quando o sujeito fica velho pensar no passado consome boa parte do tempo que ainda resta. Nesse meu último aniversário comecei a lembrar da época que era milionário, explorava minha e apostava tudo no vermelho 36. Eu devia ter uns 11 anos.

Quando era pirralho alguém da minha rua (e &#8220;minha rua&#8221; aqui significa todas as [...]]]></description>
			<content:encoded><![CDATA[<p>Quando o sujeito fica velho pensar no passado consome boa parte do tempo que ainda resta. Nesse meu último aniversário comecei a lembrar da época que era milionário, explorava minha e apostava tudo no vermelho 36. Eu devia ter uns 11 anos.</p>
<p align="center"><img title="Las Vegas" src="http://www.setantas.net/blog/wp-content/uploads/2009/09/lasvegas.png" alt="Las Vegas" /></p>
<p>Quando era pirralho alguém da minha rua (e <em>&#8220;minha rua&#8221;</em> aqui significa todas as ruas ao redor até as bordas do cemitério, que às vezes era incluído no território) teve a genialíssima idéia de inventar o dinheiro! Da mesma forma que alguém decidiu que um metal amarelo brilhante aparentemente inútil (eles não tinham processadores naquela época) valia mais que muitas vidas humanas, nós crianças decidimos que carteiras vazias de cigarro valiam algo. Lembro mais ou menos da escala: Hollywood valia 5 (tinha um cigarro bem ruinzinho que valia 1), Carlton valia 10, Camel e Marlboro eram 50, e um outro lá que todos chamavam de <em>&#8220;capa preta&#8221;</em> valia 100 (uma nota preta!). Quanto mais bling mais valor.</p>
<p>A senhora minha mãe é fumante antiga, acho até que tragava líquido aminiótico pelo cordão umbilical (por falar nisso, ela jura que não fumou na gravidez, mas não consigo acreditar nela porque isso explicaria muita coisa), e eu como mau filho que era estimulava seu vício pra pegar as carteiras vazias. O problema é que ela só fumava Hollywood o que me garantia uma renda muito baixa. Os moleques Bicho Solto eram mais empreendedores, andavam pelos bares e pelas ruas mais agitadas e faziam verdadeiras fortunas. Eu tinha de me contentar em andar olhando as sarjetas e ir pra casa às 9. Eu era classe média. Sim, a parte sobre ser milionário foi uma mentira pra prender sua atenção.</p>
<p>Mesmo todo esse dinheiro de carteiras de cigarro não podia comprar o mais reles chiclete, além de nossas necessitades básicas serem plenamente atendidas pelos pais. Então, o que nos restava fazer com o dinheiro? Ver quem era o mais rico é uma das primeiras coisas pra fazer num grupo de pessoas com dinheiro em excesso. Não tínhamos um top 100 da Forbes, mas Moacir era sem sombra de dúvida nicotinicamente podre de rico, tinha até carteira de cigarro importado. Todos se admiravam. Ele era o cara mais de rua que podia existir, e também era muito doido, do tipo Forrest Gump (me lembro agora da história de como ele ficou comovido quando meu primo o levou no puteiro &#8212; mas isso aqui não é mil e uma noites, então vamos voltar à história). E claro que foi Moacir, bilionário <em>entrepreneur</em>, que nos levou pro próximo nível das pessoas com dinheiro e sem ter com que gastar: o jogo!</p>
<p align="center"><img title="Roleta" src="http://www.setantas.net/blog/wp-content/uploads/2009/09/roulette.png" alt="Roleta" /></p>
<p>Moacir passou a andar com uma caixa, que desdobrada bem embaixo da luz de um dos poucos postes da grande ladeira no fim da rua, se tornava um cassino completo. Não exatamente completo, não tínhamos cartas, mas os dados e a roleta estavam lá pra quem quisesse apostar. <em>&#8220;Derby?! Pode ir tirando esses couros-de-rato daqui que a aposta é alta: Carlton pra cima!&#8221;, &#8220;Porra, Moacir, aceita aí meus Hollywoods que ainda tá valendo.&#8221;, &#8220;Tá, tá, tá, então aposta logo essa miséria!&#8221; </em>Cara, perdi tantos Hollywoods, mas foi melhor assim, em troca aprendi uma importante lição vendo Moacir enriquecer e todos os outros ficando pobres: no fim a casa leva.</p>
<p>Só tem um nível que nós ricaços das carteiras de cigarro não alcançamos: as putas. Nunca apareceu uma menina pra dançar no meio-fio do lado do cassino me permitindo colocar minhas carteiras vazias de Hollywood (provavelmente eu economizaria botando umas de Derby) na sua enorme calcinha de algodão.</p>
<p><map name='google_ad_map_476_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/476?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_476_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=476&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F09%2F22%2Fviva-las-vegas%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/09/22/viva-las-vegas/&via=&text=Viva Las Vegas!&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/09/22/viva-las-vegas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prince of PySide</title>
		<link>http://www.setantas.net/blog/2009/09/03/prince-of-pyside/</link>
		<comments>http://www.setantas.net/blog/2009/09/03/prince-of-pyside/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 22:27:24 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[mine]]></category>
		<category><![CDATA[pro]]></category>
		<category><![CDATA[PySide]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[silly]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/?p=463</guid>
		<description><![CDATA[



Tweet]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-464" title="princeofpyside" src="http://www.setantas.net/blog/wp-content/uploads/2009/09/princeofpyside.png" alt="princeofpyside" width="600" height="367" /></p>
<p><map name='google_ad_map_463_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/463?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_463_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=463&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F09%2F03%2Fprince-of-pyside%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/09/03/prince-of-pyside/&via=&text=Prince of PySide&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/09/03/prince-of-pyside/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shiboken</title>
		<link>http://www.setantas.net/blog/2009/08/31/shiboken/</link>
		<comments>http://www.setantas.net/blog/2009/08/31/shiboken/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 15:54:12 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[pro]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[PySide]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/?p=449</guid>
		<description><![CDATA[Last week PySide was launched, the team was glad to see the project finally go public and receive the community feedback, be it positive, negative or both. Many questions arose, like &#8220;Why duplicate efforts?&#8221; Well, I can&#8217;t say much more than what is already answered on PySide FAQ. For us (the team) the fact is [...]]]></description>
			<content:encoded><![CDATA[<p>Last week <a title="PySide" href="http://www.pyside.org">PySide</a> was launched, the team was glad to see the project finally go public and receive the community feedback, be it positive, negative or both. Many questions arose, like <em>&#8220;Why duplicate efforts?&#8221;</em> Well, I can&#8217;t say much more than what is already answered on <a title="FAQ - PySide" href="http://www.pyside.org/faq/">PySide FAQ</a>. For us (the team) the fact is that we had a task to accomplish and must perform it the best we can. That said, allow me to remind you that this is my personal blog and many of the views here written are my very own cherished opinion.</p>
<p>The other question that we&#8217;re waiting for, and my personal favorite, was <em>&#8220;Why Boost.Python?&#8221;</em>. Though one. First of all, <a title="Boost" href="http://www.boost.org/">Boost.Python</a> eases very much the creation of C++ libraries bindings for Python. How to infer which method signature to call based on the Python arguments passed to the method wrapper? Boost.Python will take care of it. Inheritance? Type conversion (in opposition to type wrapping)? You bet: Boost.Python will take care of all this for you. The feature full Boost.Python gave us a great kick start and at first we progressed very fast. Occasionally some strange bug appeared and took some time to figure out the problem through the jungle of template error messages. Part of the job anyhow, and after that: fast pace again.</p>
<p>At some point somebody checked the size of the produced binary modules. <em>&#8220;Hey guys, is that correct?&#8221;</em>, <em>&#8220;Ah, just strip the file.&#8221;</em>, <em>&#8220;Still huge.&#8221;</em>, <em>&#8220;Holy cow&#8230;&#8221;</em>. Next task: size reduction. Some redesigns reduced a good deal of megabytes, g++ flags were also helpful, but these things weren&#8217;t enough. Then a new idea: <em>&#8220;Let&#8217;s try it with the Intel C++ compiler and see what gives.&#8221;</em> It gave binary modules with feasible sizes. Good, but the test just proved that it was <strong>possible</strong> to achieve the reductions. Besides, there were still other new ideas to try, and the fact that as soon as the project was launched the community would step in and say <em>&#8220;I had this size problem with Boost.Python before. Here is how I solved it&#8230;&#8221;</em>. (Which reminds me how limited, communication wise, a project is in its non-open phase. And don&#8217;t point your finger, mister &#8212; for every open source project has it&#8217;s non-open phase, even in your head!)</p>
<p>Part of the team was growing skeptical about the size reduction problem. Why not to try <a title="CPython" href="http://en.wikipedia.org/wiki/Cpython">CPython</a> code generation right now? Well, some say you can&#8217;t change the plane&#8217;s motor while flying, and this is true. Feature wise we were almost there and the reduction was possible. Also some of us had mixed feelings about CPython. In a past project a comparison was made about writing bindings with different technologies, including CPython, to check for speed, size and the burden imposed on the developer. At the end the guy with CPython had good numbers (not stunningly better than the others, at least for the case that mattered back then), but his personal impression was that he was suffering the <a title="Stockholm syndrome" href="http://en.wikipedia.org/wiki/Stockholm_syndrome">Stockholm syndrome</a>: he knew CPython abused him, but he developed a bond with his kidnapper.</p>
<p>Still, almost every one started personal (and voluntary, aka <em>&#8220;made at home&#8221;</em>) experimentation with different CPython generators (even a ctypes one!), and in the end all the ideas (including the ones from the Boost.Python generator) were merged into a single CPython generator, called <strong>Shiboken</strong>.</p>
<h1>Shiboken</h1>
<p>Before going on with this, allow me to explain that <strong>Shiboken</strong> means absolutely nothing. Not buddhist void, I just mean that the word <strong>Shiboken</strong> has no meaning attached to it. Except, of course, <em>&#8220;generator of CPython based binding code for C/C++ libraries&#8221;</em>.</p>
<h1 id="firstHeading" style="text-align:center;">死</h1>
<h1 id="firstHeading" style="text-align:center;">某</h1>
<h1 id="firstHeading" style="text-align:center;">剣</h1>
<p style="text-align:center;"><em>Disclaimer: I don&#8217;t know a thing about Japanese language and the above kanjis are just something that I <a title="Shi" href="http://en.wiktionary.org/wiki/%E6%AD%BB">found</a> <a title="Bo" href="http://en.wiktionary.org/wiki/%E6%9F%90">at</a> <a title="Ken" href="http://en.wiktionary.org/wiki/%E5%89%A3">wikitionary</a> to match the sounds of Shiboken. Forgive me, <a title="Lauro Moura's blog" href="http://lauro.wordpress.com/">Lauro</a>. :)</em></p>
<p>The conspirators&#8217; plan was to develop the alternative generator to a point that could generate PySide bindings that pass all our unit tests, run the apps, etc, thus beign able to replace the Boost.Python front-end. For PySide users, i.e. Python programmers, the replacement would bring no impact, since the API should remain the same. The Shiboken generator is based on the same principles of the Boost.Python one: built using the <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">API Extractor</a> library, how the C++ library should be exported to Python is described on a <a title="The API Extractor Type System" href="http://www.pyside.org/docs/apiextractor/typesystem.html">Type System</a> file, and so on.</p>
<div id="attachment_450" class="wp-caption aligncenter" style="width: 610px"><img class="size-full wp-image-450" title="Shiboken Generator" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/shibokengenerator.png" alt="Shiboken Generator" width="600" height="131" /><p class="wp-caption-text">The power of Lego-fu!</p></div>
<p>When Shiboken reached a point that we&#8217;d think was good enough to start working with it at work, we presented it to our bosses and the green light was given. The Boost.Python generator will continue as the tool to generate the official PySide bindings, but with the parallel efforts we hope that Shiboken takes its place, the size reduction is achieved, and the <a title="Occam's razor" href="http://en.wikipedia.org/wiki/Occam%27s_razor">Occam&#8217;s razor</a> cut off the unnecessary entities.</p>
<div id="attachment_451" class="wp-caption aligncenter" style="width: 360px"><img class="size-full wp-image-451" title="noboostqtarch" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/noboostqtarch.png" alt="noboost" width="350" height="220" /><p class="wp-caption-text">Occam&#39;s razor demands that Boost.Python go</p></div>
<h1>C/C++ Bindings</h1>
<p>Another fix that we aim to achieve with Shiboken is to allow non-Qt C++ and C libraries to be wrapped with the generator scheme. The problem with the current Boost.Python generator is that even a non-Qt library wrapped with it will depend on Qt. Of course this is not the best we can do, but the fixing task had low priority since the PySide bindings are the main target of the work. For Shiboken we make it library agnostic from the start, specially because we do not get our chances trying to wrap the whole Qt from start: a test library with all the problems that could arise was made and is the source of all Shiboken unit tests.</p>
<h1>Shiboken Features Worth Noting</h1>
<p>Abandoning Boost.Python means abandoning some features already provided by it. One that is worth mentioning is the decision of which signature of a method should be called depending on the Python arguments passed on the call. For this to work we have to write a decisor that progressively checks the argument types until the correct signature is found. Just this? Of course not, the binding developer can use the Type System description to remove method signatures, remove/change the type of its arguments, even remove/change/set its default values! The method call decisor must take everything into account.</p>
<div id="attachment_452" class="wp-caption aligncenter" style="width: 610px"><a href="http://www.setantas.net/blog/wp-content/uploads/2009/08/overloaded.png"><img class="size-full wp-image-452 " title="Overloaded Method" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/overloaded.png" alt="Overloaded Method" width="600" height="126" /></a><p class="wp-caption-text">Debugging a multiple signature method call decisor is easier with the &quot;dumpGraph&quot; method.</p></div>
<p>No Boost.Python also means that would be harder to convert types and containers back and forth between C++ and Python. The template specialization technique was used to solve this one.</p>
<pre>template &lt;&gt; struct Converter&lt;bool&gt; {
  static PyObject* toPython(ValueHolder&lt;bool&gt; holder) {
    return PyBool_FromLong(holder.value);
  }
  static bool toCpp(PyObject* pyobj) {
    return pyobj == Py_True;
  }
};</pre>
<p>Why not generating &#8220;pyobj == Py_True&#8221; directly, you say? The above code scales better, since it will be the same for types that are composed of some primitive types inside containers inside containers, etc. Besides, the compiler could be counted on to inline short methods.</p>
<h1>&#8220;They have a plan&#8221;</h1>
<p>Right now Hugo (from <a title="PySide" href="http://www.pyside.org/">PySide</a> fame) started working on generating bare QtCore bindings without QObject and signals, then go to QObject. After that we should solve the signals problem, re-write the pieces of custom code and so on. I think after QtCore is completely done we can make a comparison with the one produced by the Boost.Python generator and see if the whole Shiboken idea can stand to its promise. The best should win for the honor and glory of open source.</p>
<p>We encourage everyone interested in the creation of Python bindings for C++ libraries to test Shiboken, report problems (we now have a component on <a title="OpenBossa" href="http://web.openbossa.org/">OpenBossa</a> <a title="Bugzilla - OpenBossa" href="http://bugs.openbossa.org">bugzilla</a>!), and tell us if something is missing for your library to work. Patches are always welcome as usual. :)</p>
<p><strong>Shiboken</strong> on gitorious: <a title="Shiboken on Gitorious" href="http://qt.gitorious.org/pyside/shiboken">http://qt.gitorious.org/pyside/shiboken</a></p>
<p><map name='google_ad_map_449_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/449?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_449_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=449&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F08%2F31%2Fshiboken%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/08/31/shiboken/&via=&text=Shiboken&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/08/31/shiboken/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Cryptonomicon</title>
		<link>http://www.setantas.net/blog/2009/08/23/cryptonomicon/</link>
		<comments>http://www.setantas.net/blog/2009/08/23/cryptonomicon/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 03:49:26 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[pt]]></category>
		<category><![CDATA[Livros]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/?p=439</guid>
		<description><![CDATA[Logo que terminei de ler Cryptonomicon, do Neal Stephenson, fiquei protelando escrever algo sobre o livro, mas seria injusto não falar uma coisa ou outra sobre ele. Vamos ver o que ainda tenho na cabeça.

O livro é um tijolo de papel que vale cada árvore. Novecentas e tantas páginas onde o escritor não tem a [...]]]></description>
			<content:encoded><![CDATA[<p>Logo que terminei de ler <strong>Cryptonomicon</strong>, do Neal Stephenson, fiquei protelando escrever algo sobre o livro, mas seria injusto não falar uma coisa ou outra sobre ele. Vamos ver o que ainda tenho na cabeça.</p>
<p><img class="aligncenter size-full wp-image-440" title="stephenson_cryptonomicon_html_49ffa56a" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/stephenson_cryptonomicon_html_49ffa56a.jpg" alt="stephenson_cryptonomicon_html_49ffa56a" width="150" height="100" /></p>
<p>O livro é um tijolo de papel que vale cada árvore. Novecentas e tantas páginas onde o escritor não tem a menor vergonha de meter um gráfico de sino (aquele da probabilidade) ou um pequeno script perl. Mais ainda, Stephenson coloca tudo de uma forma que em vez de achar difícil você se sente mais inteligente (+2 na Int enquanto o livro estiver aberto).</p>
<p>A história se desenvolve em duas épocas: a Segunda Guerra Mundial e o Tempo Presente (anos 90, na verdade). Alguns personagens dos tempos mordernos são descendentes ou versões mais velhas de personagens da época da guerra. Outros personagens são reais (ou representações romanceadas de pessoas reais), como <a title="Alan Turing" href="http://pt.wikipedia.org/wiki/Alan_Turing">Alan Turing</a> e o <a title="Douglas MacArthur" href="http://pt.wikipedia.org/wiki/Douglas_MacArthur">General MacArthur</a>, que era muito figura. O livro alterna a narrativa entre as duas épocas, o que me deixou o tempo todo pescando pistas de todas as formas que o passado poderia influenciar o presente.</p>
<p>Não é segredo que o principal tema do livro é criptografia. Na parte da estória ambientada no passado são apresentados vários temas modernos da matemática. Não de forma didática, mas pelos olhos de quem estava descobrindo as novidades com a empolgação de um explorador do ártico. Lawrence Pritchard Waterhouse, amigo pessoal de Alan Turing, é uma dessas pessoas com o cérebro tão embriagado pela matemática que é normal ter epifanias geniais qualquer que seja a situação. Quando a guerra começa a esquentar Waterhouse está num navio em Pearl Harbor como músico da bandinha. Tendo sobrevivido aos eventos conhecidos, ele é inesperadamente descoberto como matemático über-cracker extraordinaire, promovido à oficial e mandado pra quebrar códigos nazistas em <a title="Bletchley Park" href="http://pt.wikipedia.org/wiki/Bletchley_Park">Bletchley Park</a> e outros lugares.</p>
<p>Enquanto isso, nos tempos modernos, Randy Waterhouse, neto de Lawrence, é um hacker e empreendedor tentando, juntamente com seus amigos e sócios, criar um <a title="Data Haven" href="http://en.wikipedia.org/wiki/Data_haven">Data Haven</a> numa ilha do Pacífico. E caçar tesouros.</p>
<p>Nesse ponto eu dou uma parada no post tipo &#8220;resenha&#8221; e mudo pra post tipo &#8220;vou fazer como quiser&#8221;.</p>
<p>O livro tem vários personagens legais, mas vou me fixar nos Waterhouse e nas minhas situações preferidas. E em Enoch Root, claro.</p>
<p>Enoch Root é um padre que aparece nas duas épocas, praticamente inalterado. Randy define ele como um Mago. Randy também se define como um Anão e outras pessoas como Hobbits. Essas comparações de pessoas com personagens das histórias de Tolkien e RPGs sempre me arrancavam um sorriso de satisfação &#8212; isso é algo que faço com muita freqüência (designers são Elfos, desenvolvedores são Anões).</p>
<p>Avançando um pouco, Randy é trancafiado numa cadeia em algum lugar pelas Filipinas. Enoch Root arruma um jeito de ser preso na cela do lado. Lá rola um diálogo que é o meu preferido no livro: Enoch Root explicando que os alemães perderam a WW2 por serem seguidores de <strong>Ares</strong> e os Aliados venceram por serem seguidores de <strong>Atena</strong>. Ele começa questionando pra quê os gregos precisavam de dois deuses da guerra. Eles não são exatamente iguais. Ares é a pancadaria, a carnificina e a destruição &#8212; o cara é um psico. Atena é diferente, começando que ela nasceu da cabeça de Zeus. E ela não é deusa só da guerra, ela é deusa da estratégia e, mais importante, da tecnologia. A marcha de destruição alemã não era apenas física, eles atacaram desde as artes até a por eles chamada <em>&#8220;ciência judaica&#8221;</em>. Eles tocaram Einstein (ele faz uma pontinha no livro) pra fora de lá, só pra citar um. Os aliados, pelo contrário, recebem a leva de cientistas fugidos e ainda proveem o habitat natural deles: um lugar para pensarem livremente (mais uma boa verba de pesquisa). Enoch Root elabora esse ponto melhor que eu (leia o livro), mas poderia resumir assim: <em>&#8220;Smart guys have better guns&#8221;</em>.</p>
<p>Waterhouse avô é meu personagem preferido, as situações são ótimas. Ele alterna períodos de intenso trabalho intelectual com luxúria desesperada que geralmente o leva pros serviços das moças da rua da luz vermelha. Waterhouse chega a fazer um gráfico da variação de concentração ao longo do tempo: o <em>&#8220;horniness index&#8221;</em>. Os períodos de tranqüilidade após um <em>&#8220;manual override&#8221;</em> eram sempre mais curtos que os que seguiam a ida às putas (ele é um marinheiro afinal de contas). Achei esse gráfico muito mais legal que o computador que ele inventou baseado num órgão de igreja.</p>
<p>Talvez não tão legal quanto quando Waterhouse percebe na beira da praia que toda a existência envia sinais criptografados para todos os lados, e se pergunta que informações estão codificadas na freqüência das ondas.</p>
<p>O livro é grande, com seqüências de ação, sagacidades, drogas, putarias, discussões filosóficas, heroísmo, códigos, quebra de códigos, submarinos, jatos, nazistas, nerdices, dinheiro, tesouros, mais códigos, e as missões para corrigir a curva do sino realizadas pelo destacamento 2702 (originalmente chamado destacamento 2701, mas esse número dava muito na vista, sendo ele o produto dos números primos palíndromos 37 e 73 &#8212; suspeitíssimo!). Se você quiser ler e completar as enormes lacunas dessa sombra de lembrança de resenha, então corra. Se está difícil conseguir o volume tem esse <a title="Cryptonomicon" href="http://www.kulichki.com/moshkow/INOFANT/STEFENSON/cryptonomicon_engl.txt">link</a> de um dos maiores Data Havens do mundo: a mãe Rússia. спасибо!</p>
<p style="text-align:center;"><img title="stephenson_cryptonomicon_html_46ae2806" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/stephenson_cryptonomicon_html_46ae2806.jpg" alt="stephenson_cryptonomicon_html_46ae2806" width="408" height="208" /></p>
<p>P.S.: e um valeu pro Marcio pelo livro.</p>
<p><map name='google_ad_map_439_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/439?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_439_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=439&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F08%2F23%2Fcryptonomicon%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/08/23/cryptonomicon/&via=&text=Cryptonomicon&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/08/23/cryptonomicon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PySide</title>
		<link>http://www.setantas.net/blog/2009/08/22/pyside-2/</link>
		<comments>http://www.setantas.net/blog/2009/08/22/pyside-2/#comments</comments>
		<pubDate>Sat, 22 Aug 2009 21:44:13 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[en]]></category>
		<category><![CDATA[pro]]></category>
		<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[PySide]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/?p=433</guid>
		<description><![CDATA[A few days ago the project that I worked on for sometime finally went public: PySide was launched!
And &#8220;what is PySide?&#8221;, you ask me. It is a binding of the Qt4 framework for the Python language created by INdT and Nokia (Moi, tamperelaiset!) under a LGPL license. My team (not that I&#8217;m the owner, &#8220;mine&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago the project that I worked on for sometime finally went public: <a title="PySide - Python for Qt4" href="http://www.pyside.org">PySide</a> was launched!</p>
<p><a href="http://www.pyside.org"><img class="size-full wp-image-420 aligncenter" title="pyside-logo" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/pyside-logo.png" alt="PySide - Python for Qt" width="199" height="102" /></a>And <em>&#8220;what is <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a>?&#8221;</em>, you ask me. It is a binding of the <a title="Qt4" href="http://qt.nokia.com/">Qt4</a> framework for the <a title="Python" href="http://www.python.org">Python</a> language created by <a title="Instituto Nokia de Tecnologia" href="http://indt.org.br/institutional/index.php">INdT</a> and <a title="Nokia" href="http://www.nokia.com">Nokia</a> (Moi, tamperelaiset!) under a LGPL license. My team (not that I&#8217;m the owner, &#8220;mine&#8221; in the sense of <em>&#8220;our not including the listener&#8221;</em> &#8212; I think there is a plural for that in Finnish or Quenya) worked as mad and the launching was smooth: we have a positive reception from the community and the <a title="PySide - LGPL Python bindings for Qt" href="http://www.h-online.com/open/PySide-LGPL-Python-bindings-for-Qt--/news/114039">news</a> <a title="PySide - Nokia-sponsored LGPL bindings to Qt" href="http://eli.thegreenplace.net/2009/08/19/pyside-nokia-sponsored-lgpl-bindings-to-qt/">are</a> <a title="PySide - Nokia-sponsored LGPL Python bindings for Qt" href="http://www.reddit.com/r/Python/comments/9brpf/pyside_nokiasponsored_lgpl_python_bindings_for_qt/">popping</a> <a title="LGPL Python bindings for Qt released" href="http://codeposts.blogspot.com/2009/08/lgpl-python-bindings-for-qt-released.html">up</a> <a title="PySide: Python for Qt" href="http://www.osnews.com/story/22019/PySide_Python_for_Qt">everywhere</a>.</p>
<p>And we give not only the fish but also the fishing rod: the binding <strong>generator</strong> was also made available. But what is the importance of this? Since the news was given, the explanation follows.</p>
<p>But before I continue, pay attention to the little <em>Prince of Persia</em> like bottle on the <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a> logo. This nice image is a branding used in projects from the <a title="Qt Labs Americas" href="http://qtlabs.openbossa.org/en/">Qt Labs Americas</a>.</p>
<h1>The Bindings</h1>
<p>The main motivation to start the <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a> project was to provide Python bindings of the Qt4 library under a LGPL license, to follow the very own Qt4 LGPL license offer from Nokia. Many possibilities on how this should be done where analysed, and before this sentence start an endless technical discussion I must say that all the options have strengths and weaknesses, but aren&#8217;t that much different. In the end it was a mix of right-tool-for-the-job, team&#8217;s acquaintance with the technologies involved and personal taste. Just to mention a personal favorite, I really appreciate <a title="Smoke" href="http://techbase.kde.org/Development/Languages/Smoke">Smoke</a>. In the end we choose to alter an existing binding generator (more on this later) and use <a title="Boost" href="http://www.boost.org/">Boost.Python</a> as the middle-man to talk to <a title="CPython" href="http://en.wikipedia.org/wiki/CPython">CPython</a> API. To express this with colored boxes this is <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a> right now:</p>
<p><img class="aligncenter size-full wp-image-425" title="PySide architecture with Boost.Python" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/boostqtarch.png" alt="PySide architecture with Boost.Python" width="350" height="220" /></p>
<h1>The Generator</h1>
<p>Writing bindings for a library so massively huge as Qt is a task&#8230; no, it&#8217;s not a task, it is a punishment. Beign reasonable people as we are, a previous research has been made and we opt to adapt the code from <a title="QtScriptGenerator" href="http://qt.gitorious.org/qt-labs/qtscriptgenerator">QtScript Generator</a>,which is a fork of the <a title="Qt Jambi" href="http://qt.gitorious.org/qt-jambi">Qt Jambi&#8217;s Generator</a>, and both are binding generators for QtScript and Java, respectively. They&#8217;re developed by Trolltech (when it was called Trolltech).</p>
<p>The binding generation scheme works like this:</p>
<p style="text-align:center;"><img class="size-full wp-image-422 aligncenter" title="Binding Generator Scheme" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/generator.png" alt="Binding Generator Scheme" width="510" height="170" /></p>
<p>The <strong>global.h</strong> file includes all headers (or at least the desired ones) from the library beign wrapped, and is also used to define (and undefine) preprocessor macros. <strong>typesystem.xml</strong> files contains descriptions of how the library should be exported to the target language and other semantic information: rejeted classes, renames methods, types to be converted, which methods move object ownership from Python to C++ and the otherway around, and specifies where handwritten code for special cases should be inserted. If there is no need for changes, this XML will be a simple list of classes, enums and functions.</p>
<p>Notice that we not only forked the QtScript Generator, we also converted it from an monolithic application to a <strong>library + front-end generator </strong>scheme. And here is another picture to show the idea:</p>
<p><img class="aligncenter size-full wp-image-424" title="BoostPythonGenerator" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/boostgenerator1.png" alt="BoostPythonGenerator" width="510" height="111" /></p>
<p>Theoretically the projects from where we derived code could be changed to use the <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">API Extractor</a> and share this code base (and bugs, and fixes, and improvements). Nevertheless this will not be that straightforward, since we have made a number of changes to the <a title="The API Extractor Type System" href="http://www.pyside.org/docs/apiextractor/typesystem.html">typesystem format</a>, from simple things like tag renaming (mostly changing <em>&#8220;java&#8221;</em> to <em>&#8220;targetlang&#8221;</em>) to more complex things that I&#8217;ll not exemplify here. Besides that, one could write front-ends that use <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">API Extractor</a> to generate things other than bindings: class diagrams with GraphViz, statistics, something-that-i-did-not-thought-about.</p>
<p>Now for the not so beauty part. In a perfect world the C++ to Python binding generator could generate bindings for any C++ library, although, in the way it is right now the generator is useful <strong>only</strong> for Qt based libraries. Shame on us! Anyhow, taking into account that our main target was to create Qt bindings and that a beta version of them was released, I suggest you forgive us. :) Of course that it is in our plans to solve this and make the generator a useful tool for as many people as possible.</p>
<p>To much information for now! For the time beign <a title="PySide - Downloads" href="http://www.pyside.org/downloads/">download</a>, test, <a title="PySide Bugzilla" href="http://bugs.openbossa.org/">report bugs</a> and enjoy. And, if you&#8217;re feeling social, go to  <strong>#pyside</strong> channel on FreeNode and subscribe to the <a title="PySide mailing list" href="http://lists.openbossa.org/listinfo/pyside">mailing list</a>. Everybody is welcome.</p>
<div id="_mcePaste" style="overflow:hidden;position:absolute;left:-10000px;top:599px;width:1px;height:1px;">Bugzilla</div>
<p><map name='google_ad_map_433_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/433?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_433_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=433&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F08%2F22%2Fpyside-2%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/08/22/pyside-2/&via=&text=PySide&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/08/22/pyside-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PySide</title>
		<link>http://www.setantas.net/blog/2009/08/19/pyside/</link>
		<comments>http://www.setantas.net/blog/2009/08/19/pyside/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 22:50:22 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[pro]]></category>
		<category><![CDATA[pt]]></category>
		<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[PySide]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/?p=418</guid>
		<description><![CDATA[Agora sim, chega de trabalhar na moitinha igual contra-regra, o negócio agora é público: PySide foi lançado!

Sim! E o que é PySide, você pergunta? São bindings da biblioteca Qt4 para linguagem Python criados pelo INdT e a Nokia (Moi, tamperelaiset!) sob licença LGPL. Minha equipe (não sou dono dela, minha no sentido de &#8220;nossa sem [...]]]></description>
			<content:encoded><![CDATA[<p>Agora sim, chega de trabalhar na moitinha igual contra-regra, o negócio agora é público: <a title="PySide - Python for Qt4" href="http://www.pyside.org">PySide</a> foi lançado!</p>
<p style="text-align:center;"><a href="http://www.pyside.org"><img class="size-full wp-image-420 aligncenter" title="pyside-logo" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/pyside-logo.png" alt="PySide - Python for Qt" width="199" height="102" /></a></p>
<p>Sim! E o que é <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a>, você pergunta? São bindings da biblioteca <a title="Qt4" href="http://qt.nokia.com/">Qt4</a> para linguagem <a title="Python" href="http://www.python.org">Python</a> criados pelo <a title="Instituto Nokia de Tecnologia" href="http://indt.org.br/institutional/index.php">INdT</a> e a <a title="Nokia" href="http://www.nokia.com">Nokia</a> (Moi, tamperelaiset!) sob licença LGPL. Minha equipe (não sou dono dela, minha no sentido de <em>&#8220;nossa sem incluir o interlocutor&#8221;</em>) trabalhou feito louca e o lançamento foi uma beleza: tivemos um retorno positivo da comunidade e as notícias <a title="PySide - LGPL Python bindings for Qt" href="http://www.h-online.com/open/PySide-LGPL-Python-bindings-for-Qt--/news/114039">estão</a> <a title="PySide - Nokia-sponsored LGPL bindings to Qt" href="http://eli.thegreenplace.net/2009/08/19/pyside-nokia-sponsored-lgpl-bindings-to-qt/">aparecendo</a> <a title="PySide - Nokia-sponsored LGPL Python bindings for Qt" href="http://www.reddit.com/r/Python/comments/9brpf/pyside_nokiasponsored_lgpl_python_bindings_for_qt/">em</a> <a title="LGPL Python bindings for Qt released" href="http://codeposts.blogspot.com/2009/08/lgpl-python-bindings-for-qt-released.html">toda</a> <a title="PySide: Python for Qt" href="http://www.osnews.com/story/22019/PySide_Python_for_Qt">parte</a>.</p>
<p>E fornecemos não apenas o peixe mas também a vara (na boa): o <strong>gerador</strong> de bindings também está disponível. Mas qual a importância disso? Dada a notícia vou explicar com calma.</p>
<p>Antes de continuar repare na garrafinha de <em>Prince of Persia</em> no logo do <strong>PySide</strong>. É a marca usada em projetos do <a title="Qt Labs Americas" href="http://qtlabs.openbossa.org/">Qt Labs Americas</a>.</p>
<h1>Os Bindings</h1>
<p>O motivo primário da criação do <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a> foi prover bindings Python da Qt4 sob a licença LGPL, para se alinhar com a oferta da Nokia da própria Qt4. Várias possibilidades de como fazer foram analisadas, e antes dessa frase começar uma discussão técnica infinita, todas as opções tinham pontos bons e ruins, mas não tão diferentes assim. A idéia do <a title="Smoke" href="http://techbase.kde.org/Development/Languages/Smoke">Smoke</a> foi uma das que mais gostamos e vale uma menção. No fim optamos por alterar um gerador de bindings existente (mais sobre isso abaixo) e usar o <a title="Boost" href="http://www.boost.org/">Boost.Python</a> para fazer meio-campo com a API <a title="CPython" href="http://pt.wikipedia.org/wiki/CPython">CPython</a>. Trocando em diagramas coloridos esse é o <a title="PySide - Python for Qt4" href="http://www.pyside.org/">PySide</a>:</p>
<p><img class="aligncenter size-full wp-image-425" title="PySide architecture with Boost.Python" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/boostqtarch.png" alt="PySide architecture with Boost.Python" width="350" height="220" /></p>
<h1>O Gerador</h1>
<p>Escrever bindings pra uma biblioteca tão massivamente grande quanto Qt é uma tarefa&#8230; não, não é uma tarefa, é uma punição. Pessoas de bom senso que somos demos uma pesquisada por aí e optamos por adaptar o código do <a title="QtScriptGenerator" href="http://qt.gitorious.org/qt-labs/qtscriptgenerator">QtScript Generator</a>, que por sua vez é um fork do <a title="Qt Jambi" href="http://qt.gitorious.org/qt-jambi">Qt Jambi Generator</a>, e ambos são geradores de bindings QtScript e Java, respectivamente, desenvolvidos pela Trolltech (quando ela se chamava Trolltech).</p>
<p>O esquema de geração de bindings funciona assim:</p>
<p style="text-align:center;"><img class="size-full wp-image-422 aligncenter" title="Binding Generator Scheme" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/generator.png" alt="Binding Generator Scheme" width="510" height="170" /></p>
<p>O arquivo <strong>global.h</strong> inclui todos os headers (pelo menos os desejados) da biblioteca sendo processada, e também define e desdefine flags do preprocessador. Arquivos <strong>typesystem.xml</strong> são descrições de como a biblioteca deve ser exportada para a linguagem alvo: classes rejeitadas, métodos renomeados, tipos convertidos e, muito importante, códigos escritos à mão para casos especiais e onde eles devem ser inseridos. Se não houver necessidade de alterações esse xml será apenas uma simples lista de classes, enums e funções.</p>
<p>Notem que não apenas forkamos o QtScript Generator, mas a convertemos de uma aplicação monolítica num esquema lib (que chamamos de <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">API Extractor</a>) + front-end gerador. E mais uma figura pra explicar a idéia:</p>
<p><img class="aligncenter size-full wp-image-424" title="BoostPythonGenerator" src="http://www.setantas.net/blog/wp-content/uploads/2009/08/boostgenerator1.png" alt="BoostPythonGenerator" width="510" height="111" /> Teoricamente os projetos dos quais derivamos código poderiam ser alterados para usar o <a title="API Extractor" href="http://www.pyside.org/home-binding/api-extractor/">API Extractor</a> e compartilhar essa base de código (e bugs, e fixes, e melhorias). Além disso, o sujeito pode escrever front-ends que gerem outras coisas que não código: grafos de relacionamento entre as classes, estatísticas, algo-que-eu-não-pensei.</p>
<p>Agora a parte não tão bela. Num mundo perfeito o gerador de bindings C++ para Python geraria bindings de qualquer biblioteca C++ para Python, contudo da forma que se encontra agora o gerador serve <strong>apenas</strong> para bibliotecas baseadas em Qt. Grande vergonha! Considerando que o foco era criar o bindings Qt e os lançamos em versão beta, sugiro nos perdoar. :) Claro que está nos planos resolver isso e tornar o gerador uma ferramente genérica e útil para mais pessoas.</p>
<p>Informação demais! Por hora, <a title="PySide - Downloads" href="http://www.pyside.org/downloads/">baixem</a>, testem, <a title="PySide Bugzilla" href="http://bugs.openbossa.org/">relatem bugs</a> e aproveitem. E se estiverem se sentindo sociais entrem no canal <strong>#pyside</strong> no FreeNode e assinem a <a title="PySide mailing list" href="http://lists.openbossa.org/listinfo/pyside">lista de discussão</a>.</p>
<div id="_mcePaste" style="overflow:hidden;position:absolute;left:-10000px;top:599px;width:1px;height:1px;">Bugzilla</div>
<p><map name='google_ad_map_418_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/418?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_418_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=418&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F08%2F19%2Fpyside%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/08/19/pyside/&via=&text=PySide&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/08/19/pyside/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Bible pr0n</title>
		<link>http://www.setantas.net/blog/2009/06/14/bible-pr0n/</link>
		<comments>http://www.setantas.net/blog/2009/06/14/bible-pr0n/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 20:22:52 +0000</pubDate>
		<dc:creator>setanta</dc:creator>
				<category><![CDATA[mine]]></category>
		<category><![CDATA[pt]]></category>
		<category><![CDATA[Livros]]></category>

		<guid isPermaLink="false">http://setanta.wordpress.com/?p=390</guid>
		<description><![CDATA[Escrevo isso pra todos aqueles, incluindo a mim (fala, Amin!), que têm tanto receio de serem vistos lendo uma bíblia quanto de serem pegos pela mãe com uma Playboy da Cláudia Ohana na mão esquerda, fato vergonhoso pela mãe, pela outra mão, e ainda pelo gosto bizarro. (Fosse você um adolescente da família Van Helsing [...]]]></description>
			<content:encoded><![CDATA[<p>Escrevo isso pra todos aqueles, incluindo a mim (fala, Amin!), que têm tanto receio de serem vistos lendo uma bíblia quanto de serem pegos pela mãe com uma Playboy da Cláudia Ohana na mão esquerda, fato vergonhoso pela mãe, pela outra mão, e ainda pelo gosto bizarro. (Fosse você um adolescente da família Van Helsing poderia alegar estudo privado de licantropia pubiana, mas isso ainda não explicaria a estaca na outra mão, que todos Van Helsing sabem se tratar de arma contra vampiros, não com lobis&#8230; seja lá o que for que está escondido embaixo daqueles pêlos.)</p>
<p>Imagino que o parêntese do último parágrafo cobre todo pr0n desse texto.</p>
<p>A repulsa pela a bíblia por parte das pessoas racionais e outros bichos parecidos provavelmente é gerada por causa do que ela e as pessoas que vendem esse peixe representam do que pelo conteúdo. Não vai faltar quem diga quantas mortes, guerras e manhãs de domingo entediantes aconteceram por causa de religião e tudo que lhe é relacionado. Também sobre a irracionalidade que causa nas pessoas e por aí vai. Por compartilhar vagamente dessas opiniões por muito tempo (e por ser importunado pra participar de grupos de estudo bíblicos de quanto em vez) algum mecanismo automático na minha cabeça colocava uma etiqueta de &#8220;anti- ou semi-racional&#8221; em qualquer pessoa segurando um livro preto de letras douradas e lateral das folhas vermelhas.</p>
<div class="wp-caption aligncenter" style="width: 231px"><a href="http://commons.wikimedia.org/wiki/File:Roman_Coin_with_Augustus_%28Octavian%29.jpg"><img title="Moeda Romana" src="../files/2009/06/roman_coin_with_augustus_octavian.jpg" alt="Moeda Romana" width="221" height="221" /></a><p class="wp-caption-text">Moeda Romana com Otávio Augusto</p></div>
<p>Então eu esqueço esses problemas e vou ler qualquer outra coisa <em>&#8220;de nível&#8221;</em>, o que é esperado de uma pessoa racional. Vou de <em>&#8220;A Desobediência Civil&#8221;</em> de <strong>Henry Thoreau</strong>. <em>&#8220;Sob um governo que prende qualquer homem injustamente, o único lugar digno para um homem justo é também a prisão.&#8221;</em> É assim que se fala, Thoreau! (Embora eu mesmo não queira ir pra cadeia, e talvez você não tivesse ouvido falar de algo como Carandiru.) Texto vai, texto vem, chega na parte sobre governo, impostos e ele me vem com essa citação:</p>
<blockquote>
<p style="text-align:left;"><em>Cristo respondeu aos seguidores de Herodes de acordo com a situação deles. &#8220;Mostrem-me o dinheiro dos tributos&#8221;, disse ele; e um deles tirou do bolso uma moeda. Disse então Jesus Cristo: &#8220;Se vocês usam o dinheiro com a imagem de César, dinheiro que ele colocou em circulação e ao qual ele deu valor, ou seja, se vocês são homens do Estado e estão felizes de se aproveitar das vantagens do governo de César, então paguem-no por isso quando ele o exigir. Por­tanto, dai a César o que é de César, e a Deus o que é de Deus&#8221;; Cristo não lhes disse nada sobre como distinguir um do outro; eles não queriam saber isso.</em><br />
<a title="A Desobediência Civil" href="http://www.culturabrasil.org/desobedienciacivil.htm">A Desobediência Civil</a></p>
</blockquote>
<p>Muito esperto Jesus, recebeu a bola e devolveu com efeito.</p>
<div id="attachment_394" class="wp-caption aligncenter" style="width: 173px"><a href="http://commons.wikimedia.org/wiki/File:RWS-10-Wheel_of_Fortune.jpg"><img class="size-full wp-image-394" title="A Roda da Fortuna" src="http://www.setantas.net/blog/wp-content/uploads/2009/06/rws-10-wheel_of_fortune.jpg" alt="A Roda da Fortuna" width="163" height="270" /></a><p class="wp-caption-text">A Roda da Fortuna</p></div>
<p>Depois fui pra <strong>George Orwell</strong>. Tem um ensaio chamado <a title="Politics and the English Language" href="http://www.george-orwell.org/Politics_and_the_English_Language/0.html"><em>&#8220;Politics and the English Language&#8221;</em></a>, onde ele discute como o pensamento de uma sociedade decadente corrompe a língua e como a língua corrompida aumenta ainda mais a decadência. Essa corrupção aparece na forma de textos vagos, usando uma colagem de frases prontas que esconde o que o autor quer dizer (às vezes dele mesmo) e ainda dão umas duas mãos de tinta de respeitabilidade em cima de baboseiras que se ditas claramente seriam rejeitadas no mesmo instante. Num dado momento Orwell mostra um texto claro, com imagens fortes e que passa a idéia básica do autor muito bem:</p>
<blockquote><p><em>I returned, and saw under the sun, that the race is not to the swift, nor the battle to the strong, neither yet bread to the wise, nor yet riches to men of understanding, nor yet favor to men of skill; but time and chance to them all.</em></p>
<p><em>Voltei-me, e vi debaixo do sol que não é dos ligeiros a carreira, nem dos fortes a batalha, nem tampouco dos sábios o pão, nem tampouco dos prudentes as riquezas, nem tampouco dos entendidos o favor, mas que o tempo e a oportunidade ocorrem a todos. </em>(Tradução de alguém na internet.)<em><br />
</em></p>
</blockquote>
<p>E para demostrar seu ponto de vista reescreve o trecho no que ele chama de <em><em>&#8220;inglês moderno&#8221;</em></em>:</p>
<blockquote><p><em>Objective consideration of contemporary phenomena compels the conclusion that success or failure in competitive activities exhibits no tendency to be commensurate with innate capacity, but that a considerable element of the unpredictable must invariably be taken into account.</em></p>
<p><em>Consideração objetiva de fenômenos contemporâneos compele a conclusão de que sucesso ou fracasso em atividades competitivas não exibe qualquer tendência a ser passível de redução à capacidades inatas, mas que a considerável influência do elemento da imprevisíbilidade deve ser levada em consideração.</em> (Minha tradução.)</p>
</blockquote>
<p>Essa comparação ilustra bem a idéia do ensaio, e o primeiro texto achei excelente (em português e inglês), quem o escreveu deve ter vivido o que dizia, e qualquer um lendo já deve ter passado algo assim. Quero dizer, é o tipo de preocupação com a qual todos podem se identificar. Recomendo duplamente o <a title="Politics and the English Language" href="http://www.george-orwell.org/Politics_and_the_English_Language/0.html"><em>ensaio</em></a>. E também o <a title="Eclesiastes 9" href="http://www.bibliaonline.com.br/acf/ec/9">restante do texto-exemplo</a>.</p>
<div id="attachment_397" class="wp-caption aligncenter" style="width: 310px"><img class="size-full wp-image-397" title="holypr0n" src="http://www.setantas.net/blog/wp-content/uploads/2009/06/holypr0n.png" alt="Holy Pr0n!" width="300" height="251" /><p class="wp-caption-text">Holy Pr0n!</p></div>
<p>Outra coisa que acho legal é literatura inglesa, embora não tenha tempo e memória pra ficar esnobando nos círculos sociais por aí :P. Teve uma época que trabalhei numa biblioteca de faculdade e um livro encontrado por acaso (todos eram) e devorado (e os detalhes esquecidos. sabe, memória e tals, dammit!) chamava-se <a title="A Literatura Inglesa" href="http://www.atica.com.br/catalogo/?i=9788508058846"><em>&#8220;A Literatura Inglesa&#8221;</em></a> de <strong>Anthony Burgess</strong> (o cara de <strong>Laranja Mecânica</strong> (o autor, não o personagem)). O livro foi escrito como um mastigadão (no bom sentido) de literatura inglesa pra ajudar alunos do Burgess em algum lugar pela Malásia. A prova final de inglês incluía o conhecimento de obras literárias um tanto alienígenas pros caras de lá e o livro adicionava um pouco de contexto histórico. Pra um livro escolar achei esse um dos mais agradáveis de ler (não contando os trechos legais em livros de <em>&#8220;Comunicação e Expressão&#8221;</em>, mas esses acabavam logo e não tinha livraria na minha cidade pra comprar a versão integral) e demoliu uns muros velhos da minha antiga aversão à literatura.</p>
<p>Burgess começa falando das origens da língua, saxões, normandos e tudo mais, até que chega num capítulo sem número entre o 5 e o 6 com o seguinte título: <em>&#8220;Interlúdio &#8211; A Bíblia inglesa&#8221;</em>. E o primeiro parágrafo é o seguinte:</p>
<blockquote><p><em>Vamos examinar muito sumariamente um livro cuja influência sobre a escrita, a fala e o pensamento inglês foi, e ainda é, imansa. A Bíblia não é basicamente literatura &#8211; é o livro sagrado do cristianismo -, mas recentemente vem se afirmando uma tendência crescente para apreciar a Bíblia por suas qualidades artísticas, para vê-la não só como a &#8220;Palavra de Deus&#8221;, mas como uma obra de grandes escritores. Sejam quais forem nossas crenças religiosas, se desejarmos ter uma apreciação integral do desenvolvimento da literatura inglesa, não podemos nos arriscar a negligenciar a Bíblia: seu impacto puramente literário nos escritores ingleses é talvez grande demais para ser medido.</em></p>
</blockquote>
<p>A tradução da Bíblia (agora que tenho sua atenção posso usar o &#8216;B&#8217; maiúsculo sem parecer um carola) para o inglês foi encomendada pelo Rei James I. A tarefa foi realizada (com muito cuidado) por 47 eruditos de 1604 até 1611 (foi muito cuidado mesmo). No final entregaram um texto tão bom que segura audiências até os dias de hoje. Segundo Burguess: <em>&#8220;Não há escritopr que não tenha sido influenciado por ela &#8211; até mesmo escritores como Bernard Shaw e H. G. Wells, apesar de não serem cristãos, acabaram sucumbindo à sua força.&#8221;</em></p>
<p>Outro dia comprei uma King Jame&#8217;s Bible, logo de cara gostei dessa parte (<a title="Genesis 1:2" href="http://kingjbible.com/genesis/1.htm">Genesis 1:2</a>):</p>
<blockquote><p><em>The earth was formless and void, and darkness was over the surface of the deep, and the Spirit of God was moving over the surface of the waters.</em></p>
<p>(<em>E a terra era sem forma e vazia; e havia trevas sobre a face do abismo; e o Espírito de Deus se movia sobre a face das águas.</em>)</p>
</blockquote>
<p>Não sei se é tietagem minha com a língua inglesa ou se a versão em português me lembra ser acordado à força no domingo pra continuar dormindo numa posição desconfortável na igreja, mas gosto mais da versão Jamesiana do que a tradução nos parênteses. As palavras em <em>&#8220;formless and void&#8221;</em> e <em>&#8220;darkness was over the surface of the deep&#8221;</em> soam tão bem. E <em>&#8220;the Spirit of God was moving over the surface of the waters&#8221;</em> gera uma imagem mental do <em>&#8220;Espírito de Deus&#8221;</em> sendo uma Jamanta (não o caminhão, ou aquele louco de uma novela esquecida &#8211; o que nos leva a outra tietagem: <em>&#8220;Jamanta&#8221;</em> simplesmente não soa tão bem quanto <em>&#8220;Manta Ray&#8221;</em>).</p>
<div id="attachment_399" class="wp-caption aligncenter" style="width: 410px"><a href="http://commons.wikimedia.org/wiki/File:Manta_birostris-NOAA.jpg"><img class="size-full wp-image-399" title="mantaray" src="http://www.setantas.net/blog/wp-content/uploads/2009/06/mantaray1.png" alt="&quot;Then God said, 'Let there be light'; and there was light.&quot;" width="400" height="274" /></a><p class="wp-caption-text">&quot;Then God said, &#39;Let there be light&#39;; and there was light.&quot;</p></div>
<p>Saindo da literatura e me interessando por eventos recentes. Todos (que pensam) já se perguntaram quanto do terrorismo fundamentalista islâmico é coisa de fundamentalistas, se o islamismo é mesmo violento em seu núcleo, ou se é inerente de qualquer religião, já que elas causam mortes guerras e constrangimento, como quando você é flagrado por seus amigos racionais lendo a Bíblia.</p>
<p>Esse assunto em particular é bem espinhento. Se você se der ao trabalho de procurar vai ter seu saco ou ovários enchidos até o limite com opiniões que vão de um extremo politicamente correto onde tudo é bom, todos são bons, ninguém pode ser ofendido e que mulheres de burka trancadas em casa são felizes do jeito delas, até o outro extremo (lá pelo lado direito) com pessoas que tudo que precisam é uma desculpa pra expulsar/matar/desintegrar os &#8220;alienígenas indesejáveis&#8221; do seu país.</p>
<div id="attachment_401" class="wp-caption aligncenter" style="width: 270px"><a href="http://www.elpais.com/fotografia/periodista/Oriana/Fallaci/imagen/1963/elpdiacul/20080724elpepucul_19/Ies/"><img class="size-full wp-image-401" title="Oriana Fallaci" src="http://www.setantas.net/blog/wp-content/uploads/2009/06/orianafallaci.png" alt="Oriana Fallaci" width="260" height="260" /></a><p class="wp-caption-text">Oriana Fallaci (foto &quot;emprestada&quot; de El País)</p></div>
<p>Persistindo dá pra encontrar umas pessoas interessantes, como <a title="Wikipédia: Ayaan Hirsi Ali" href="http://pt.wikipedia.org/wiki/Ayaan_Hirsi_Ali">Ayaan Hirsi Ali</a>, aquela moça da Somália que escapou da família pra Europa e chegou a parlamentar nos Países Baixos. Ou a menos famosa (pelo menos pra mim) <a title="Wikipédia: Oriana Fallaci" href="http://pt.wikipedia.org/wiki/Oriana_Fallaci">Oriana Fallaci</a>, que aos 10 anos participou da <strong>Resistência Italiana</strong>, aos 16 era repórter, foi ao Vietnam como correspondente 12 vezes, e por aí vai. Meu episódio preferido é o da entrevista com o aiatolá Khomeini em 1979:</p>
<blockquote><p><em>&#8220;Como é possível nadar com um chador [traje feminino que cobre todo o corpo, deixando apenas os olhos de fora]?&#8221;. A resposta do líder, Oriana escreveu depois no New York Times, foi que ela não era obrigada a usar um, já que se tratava de uma peça de roupa para mulheres islâmicas respeitáveis. A jornalista, então, rasgou seu chador na frente de Khomeini.</em><br />
<a title="Morre a polêmica jornalista e escritora italiana" href="http://observatorio.ultimosegundo.ig.com.br/artigos.asp?cod=399MEM001"><span>Morre a polêmica jornalista e escritora italiana</span></a></p>
</blockquote>
<p>Mas o que interessa nesse texto é como ela se define como Ateísta Cristã no livro <a title="Wikipédia: A Força da Razão" href="http://pt.wikipedia.org/wiki/A_For%C3%A7a_da_Raz%C3%A3o">A Força da Razão</a>. Dizem que o livro em si é tão polêmico que devia vir com um martelo e uma caixa de vidro escrita <em>&#8220;Quebre em Caso de Emergência&#8221;</em>, mas voltemos à afirmação:</p>
<blockquote><p><em>Sou uma Cristã porque gosto do discurso que está nas raízes do Cristianismo. Porque ele me convence. Ele me seduz&#8230; Quero dizer, o discurso concebido por Jesus de Nazaré&#8230; que&#8230; se concentra no Homem. Que adimitindo o livre-arbítrio, clama pela consciência do Homem, nos faz responsáveis por nossas ações. Mestres de nosso destino. Eu vejo um hino à Razão, uma renovação do pensamento claro&#8230; escolha&#8230; a redescoberta da liberdade. A redenção da liberdade&#8230; uma idéia que ninguém jamais teve&#8230; A idéia de um Deus que se tornou Homem&#8230; Que falando de um Criador&#8230; se apresenta como seu Filho e explica que todos os homens são irmãos de seu Filho&#8230; capaz de exercer sua própria essência divina&#8230; pregando a Bondade que é o fruto da Razão, da Liberdade, espalhando o Amor&#8230; Jesus&#8230; como um homem&#8230; aborda o tema do secularismo&#8230; ele impede os covardes que estão para apedrejar a adúltera&#8230; ele ataca a escravidão&#8230; ele luta&#8230; ele morre. Sem morrer pois a Vida não morre. A Vida sempre ressucita, Vida é eterna. E, junto com o discurso sobre a Razão, sobre a Liberdade, este é o ponto que mais me convence&#8230; a negação da Morte, a apoteose da Vida&#8230; sua alternativa é a Não-Existência. E vamos encarar: tal é o princípio que guia e alimenta nossa civilização.</em></p>
</blockquote>
<p>Essa tradução é do único trecho que pude encontrar na internet (sem recorrer a torrents de PDFs) onde Oriana Fallaci elabora essa idéia de Ateísmo Cristão dela. Veio de um artigo de uma revista conservadora norte-americana. Os conservadores provavelmente vão pegar a <a title="Morre polêmica jornalista e escritora Oriana Fallaci" href="http://www.midiaindependente.org/pt/blue/2006/09/360878.shtml">finada</a> como Joana D&#8217;Arc involuntária deles ou sei lá, mas esse é ainda outro problema, que de fato não é meu.</p>
<p>O meu problema é que já escrevi bastante. Preciso pensar como finalizar isso tudo e botar umas figuras legais pra disfarçar a compridez do texto. Opa! Falei isso em voz alta?!</p>
<p>A conclusão não sagaz é o bom e velho <em>&#8220;não julgue o livro pela capa&#8221;</em> que o He-Man diria num final de episódio. Pensando mais um pouco dá pra perceber (eu pelo menos) que tomamos muita coisa como garantida, como esperar um comportamento decente por parte dos assim chamados Outros (citação obrigatória do Luck (não Luke): <em>&#8220;Não se preocupe com os outros, tem muitos mais de onde esses vieram.&#8221;</em>), ou que a civilização (no sentido de educação e respeito, não no sentido de eletrônicos chineses feitos por trabalhadores sem assistência social) brotou de grátis do nada como o mundo que o Grande Deus Jamanta tirou do vácuo. Bom, tem uma meia dúzia de idéias que fazem sua vida não tão ruim quanto a da galera num filme de Mad Max que, dentre outros lugares, veio da Bíblia. Por exemplo: <em>&#8220;E como vós quereis que os homens vos façam, da mesma maneira lhes fazei vós, também.&#8221;</em>, Lucas 6:31; ou <em>&#8220;And as ye would that men should do to you, do ye also to them likewise.&#8221;</em>, Luke 6:31. Então se me encontrarem lendo uma Bíblia por aí lembre de tratar os outros como gostaria de ser tratado e não me encha o saco. Aliás, sinta-se livre pra tratar os outros direito (estou levando em consideração que você não é masoquista), quer saber, pra ficar mais fácil ainda: deixe-os em paz. Do que estamos agora pra isso já seria uma grande melhora.</p>
<p><map name='google_ad_map_390_74ab9b1e764918ae'>
<area shape='rect' href='http://imageads.googleadservices.com/pagead/imgclick/390?pos=0' coords='1,2,367,28' />
<area shape='rect' href='http://services.google.com/feedback/abg' coords='384,10,453,23'/></map>
<img usemap='#google_ad_map_390_74ab9b1e764918ae' border='0' src='http://imageads.googleadservices.com/pagead/ads?format=468x30_aff_img&amp;client=&amp;channel=&amp;output=png&amp;cuid=390&amp;url= http%3A%2F%2Fwww.setantas.net%2Fblog%2F2009%2F06%2F14%2Fbible-pr0n%2F' /></p><div style="float: left; margin-right: 10px;"><a href="http://twitter.com/share?url=http://www.setantas.net/blog/2009/06/14/bible-pr0n/&via=&text=Bible pr0n&related=:&lang=en&count=horizontal" class="twitter-share-button">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>]]></content:encoded>
			<wfw:commentRss>http://www.setantas.net/blog/2009/06/14/bible-pr0n/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 2.433 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-05 17:57:27 -->

