ffi - história, performance e felicidade com ruby
DESCRIPTION
Às vezes o Ruby não resolve nosso problema, mesmo com o melhor dos algoritmos. Não se acanhe: o C é seu amigo, e nada mais fácil que aproveitar uma biblioteca já existente com Ruby FFI.TRANSCRIPT
![Page 1: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/1.jpg)
FFI História, performance e felicidade com Ruby
Vitor Capela
domingo, 3 de março de 13
![Page 2: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/2.jpg)
@dodecaphonic
domingo, 3 de março de 13
Sou @dodecaphonic no Twitter. Fico com essa cara quando o computador não faz o que eu mando.
![Page 3: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/3.jpg)
Meu trabalho às vezes exige que eu transforme isto...
domingo, 3 de março de 13
Eu trabalho com geoprocessamento. Isso envolve tanto fazer coisas babacas com Google Maps como transformar uma nuvem de pontos de um levantamento a laser...
![Page 4: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/4.jpg)
... nisto.
domingo, 3 de março de 13
... em uma malha de triângulos. Essa malha pode ser um terreno em que algo vai ser construído, pode ser o levantamento do relevo para um estudo hidrológico, pode ser um scan para modelagem de um projeto de reconstrução.
![Page 5: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/5.jpg)
A gente ama Ruby.O Ruby ama a gente também.❤
domingo, 3 de março de 13
E eu gosto de fazer isso com Ruby. É muito gratificante dar uma solução sucinta, ou então bem flexível, a problemas que em linguagens tradicionais do mercado seriam enfadonhos. Há oito anos ele é meu canivete suíço.
![Page 6: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/6.jpg)
A gente ama Ruby.O Ruby ama a gente também.❤
domingo, 3 de março de 13
E eu gosto de fazer isso com Ruby. É muito gratificante dar uma solução sucinta, ou então bem flexível, a problemas que em linguagens tradicionais do mercado seriam enfadonhos. Há oito anos ele é meu canivete suíço.
![Page 7: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/7.jpg)
Mas às vezes o amor não resolve.
domingo, 3 de março de 13
Sendo muito honesto, no entanto, nem sempre é a solução ideal.
![Page 8: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/8.jpg)
Vamos combinar, gente: tem vezes que o Ruby não é rápido o bastante.
domingo, 3 de março de 13
Às vezes seus problemas recaem justamente sobre os pontos fracos da linguagem: você precisa de previsibilidade nas alocações de memória, de altíssimo desempenho numérico, de soluções que tomem o mínimo possível de tempo.
![Page 9: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/9.jpg)
Vamos combinar, gente: tem vezes que o Ruby não é rápido o bastante.
“Não é verdade: você precisa apenas de algoritmos melhores!”
domingo, 3 de março de 13
Às vezes seus problemas recaem justamente sobre os pontos fracos da linguagem: você precisa de previsibilidade nas alocações de memória, de altíssimo desempenho numérico, de soluções que tomem o mínimo possível de tempo.
![Page 10: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/10.jpg)
Vamos combinar, gente: tem vezes que o Ruby não é rápido o bastante.
“Não é verdade: você precisa apenas de algoritmos melhores!”
“Quem se importa? 99% dos problemas se resumem a IO.”
domingo, 3 de março de 13
Às vezes seus problemas recaem justamente sobre os pontos fracos da linguagem: você precisa de previsibilidade nas alocações de memória, de altíssimo desempenho numérico, de soluções que tomem o mínimo possível de tempo.
![Page 11: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/11.jpg)
Vamos combinar, gente: tem vezes que o Ruby não é rápido o bastante.
“Não é verdade: você precisa apenas de algoritmos melhores!”
“Quem se importa? 99% dos problemas se resumem a IO.”
E se eu já tiver tentado ?
domingo, 3 de março de 13
Às vezes seus problemas recaem justamente sobre os pontos fracos da linguagem: você precisa de previsibilidade nas alocações de memória, de altíssimo desempenho numérico, de soluções que tomem o mínimo possível de tempo.
![Page 12: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/12.jpg)
Vamos combinar, gente: tem vezes que o Ruby não é rápido o bastante.
“Não é verdade: você precisa apenas de algoritmos melhores!”
“Quem se importa? 99% dos problemas se resumem a IO.”
E se eu já tiver tentado ?
Pois é: 99%, não 100%.
domingo, 3 de março de 13
Às vezes seus problemas recaem justamente sobre os pontos fracos da linguagem: você precisa de previsibilidade nas alocações de memória, de altíssimo desempenho numérico, de soluções que tomem o mínimo possível de tempo.
![Page 13: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/13.jpg)
“Então vá programar em <Python|Java|Scala|Clojure|Haskell...>!”
domingo, 3 de março de 13
Já ouvi e já disse para mim mesmo algumas vezes: vá para outras linguagens. E já fui: resolvo e resolvi coisas com C++, aplico Scala aqui e ali, faço o que for preciso se o Ruby não der conta.
![Page 14: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/14.jpg)
A gente ama o Ruby.O Ruby ama a gente também.❤EU
MIMAMO
domingo, 3 de março de 13
Mas isso não muda o fato de que quero usá-lo sempre que possível.
![Page 15: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/15.jpg)
A gente ama o Ruby.O Ruby ama a gente também.❤EU
MIMAMO
domingo, 3 de março de 13
Mas isso não muda o fato de que quero usá-lo sempre que possível.
![Page 16: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/16.jpg)
Se eu quero me manter programando em Ruby sem comprometer as necessidades dos meus projetos, a solução é apelar para o C*.
* Depois de tentar o JRuby, claro.
domingo, 3 de março de 13
Com isso em mente, sempre que um problema aperta eu tento primeiro ir para o JRuby (com invokedynamic ligado); se ainda assim não for o bastante, meu (nosso) melhor amigo ainda é o C.
![Page 17: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/17.jpg)
RUBY & Cdomingo, 3 de março de 13
![Page 18: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/18.jpg)
A gente ainda estava aprendendo o beabá e o C já resolvia problemas muito complicados.
domingo, 3 de março de 13
Às vezes a gente tem a impressão de que o mundo começou quando passamos a dar atenção a ele. Que todos os nossos problemas são novos ou únicos de alguma maneira. Os barbudos nos laboratórios escuros espalhados pelo mundo inventaram a Internet e o Unix enquanto a gente nem pensava em nascer.
![Page 19: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/19.jpg)
Isso significa que há bibliotecas às pencas, várias extremamente maduras e mantidas há décadas.
domingo, 3 de março de 13
O legado (o BOM legado) é imenso.
![Page 20: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/20.jpg)
Ainda não há uma gem para resolver qualquer parada.
domingo, 3 de março de 13
Por mais que milhares de gems pipoquem a cada mês, não há solução para tudo. Encontro isso todos os dias no meu trabalho.
![Page 21: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/21.jpg)
ruby-ffi é o menor caminho entre seu programa Ruby e alguma biblioteca supimpa (e rápida!) que já esteja por aí.
domingo, 3 de março de 13
E para aproveitar esse legado, a melhor coisa atualmente é usar o ruby-ffi.
![Page 22: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/22.jpg)
FOREIGNFUNCTIONINTERFACE
Java.NETPythonMobile JS
JNIP/InvokectypesPhoneGap
domingo, 3 de março de 13
O que é uma FFI, afinal? Já falei disso algumas vezes sem dar uma definição. FFI é um jeito de ligar duas linguagens díspares de modo que uma possa fazer uso da outra.
![Page 23: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/23.jpg)
FOREIGNFUNCTIONINTERFACE
Java.NETPythonMobile JS
JNIP/InvokectypesPhoneGap
Ruby
domingo, 3 de março de 13
O que é uma FFI, afinal? Já falei disso algumas vezes sem dar uma definição. FFI é um jeito de ligar duas linguagens díspares de modo que uma possa fazer uso da outra.
![Page 24: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/24.jpg)
FOREIGNFUNCTIONINTERFACE
Java.NETPythonMobile JS
JNIP/InvokectypesPhoneGap
Ruby
domingo, 3 de março de 13
O que é uma FFI, afinal? Já falei disso algumas vezes sem dar uma definição. FFI é um jeito de ligar duas linguagens díspares de modo que uma possa fazer uso da outra.
![Page 25: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/25.jpg)
FOREIGNFUNCTIONINTERFACE
Java.NETPythonMobile JS
JNIP/InvokectypesPhoneGap
Ruby ruby-ffi
domingo, 3 de março de 13
O que é uma FFI, afinal? Já falei disso algumas vezes sem dar uma definição. FFI é um jeito de ligar duas linguagens díspares de modo que uma possa fazer uso da outra.
![Page 26: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/26.jpg)
Uma FFI permite que você chame funções em uma outra linguagem.
domingo, 3 de março de 13
![Page 27: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/27.jpg)
“Mas qual é a diferença de escrever uma extensão em C?”
domingo, 3 de março de 13
![Page 28: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/28.jpg)
domingo, 3 de março de 13
Não é preciso saber programar em C, ou TER que programar em C, para poder usar uma biblioteca. Isso significa também que você não precisa compilar nada (o que é especialmente bom no Windows).
![Page 29: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/29.jpg)
Você só precisa escrever Ruby.
domingo, 3 de março de 13
Não é preciso saber programar em C, ou TER que programar em C, para poder usar uma biblioteca. Isso significa também que você não precisa compilar nada (o que é especialmente bom no Windows).
![Page 30: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/30.jpg)
Você não precisa de headers ou da versão de desenvolvimento da biblioteca para distribuir sua gem.
domingo, 3 de março de 13
![Page 31: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/31.jpg)
Você pode usar o resultado em qualquer Ruby (MRI, JRuby, Rubinius, Maglev, ...) sem nenhuma modificação ou restrição.
domingo, 3 de março de 13
Seu resultado não fica restrito ao MRI, nem sujeito às idiossincrasias das camadas de adaptação de extensões C que o JRuby e Rubinius oferecem.
![Page 32: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/32.jpg)
Você não corre o risco da sua gem quebrar quando/se mudar a API de extensão do MRI.
domingo, 3 de março de 13
![Page 33: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/33.jpg)
É muito fácil de usar.
domingo, 3 de março de 13
![Page 34: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/34.jpg)
MESHERATOR
domingo, 3 de março de 13
Para ilustrar o ganho que uma biblioteca em C pode trazer a um projeto, escrevi um pequeno demo. “MESHERATOR” - MESH GENERATOR, um gerador de malhas trianguladas. Muito criativo.
![Page 35: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/35.jpg)
Transformar isto...
domingo, 3 de março de 13
E se vocês se lembram do começo da apresentação, meu objetivo era sair disto...
![Page 36: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/36.jpg)
... nisto.
domingo, 3 de março de 13
... para isto.
![Page 37: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/37.jpg)
Este cara sabe como triangular nuvens de pontos muito rapidamente.
Sua biblioteca, por não ser em Ruby, não tem um nome criativo ou engraçadinho: é TRIANGLE, mesmo.
JONATHAN SHEWCHUCK
domingo, 3 de março de 13
![Page 38: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/38.jpg)
DEMO
domingo, 3 de março de 13
![Page 39: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/39.jpg)
void triangulate(char *, struct triangulateio *, struct triangulateio *, struct triangulateio *); void trifree(VOID *memptr);
A API é bem pequena.
Uma string com as opções. A estrutura de entrada e saída do algoritmo.
domingo, 3 de março de 13
Não há muito a encapsular para usar essa biblioteca. char* em C é uma string. triangulateio é uma estrutura de dados. * é um ponteiro. “triangulate” transforma a nuvem de pontos em triângulos; “trifree” permite que eu libere a memória alocada pelo algoritmo.
![Page 40: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/40.jpg)
struct triangulateio { REAL *pointlist; /* In / out */ REAL *pointattributelist; /* In / out */ int *pointmarkerlist; /* In / out */ int numberofpoints; /* In / out */ int numberofpointattributes; /* In / out */ int *trianglelist; /* In / out */ REAL *triangleattributelist; /* In / out */ REAL *trianglearealist; /* In only */ int *neighborlist; /* Out only */ int numberoftriangles; /* In / out */ int numberofcorners; /* In / out */ int numberoftriangleattributes; /* In / out */ int *segmentlist; /* In / out */ int *segmentmarkerlist; /* In / out */ int numberofsegments; /* In / out */ REAL *holelist; /* In / pointer to array copied out */ int numberofholes; /* In / copied out */ REAL *regionlist; /* In / pointer to array copied out */ int numberofregions; /* In / copied out */ int *edgelist; /* Out only */ int *edgemarkerlist; /* Not used with Voronoi diagram; out only */ REAL *normlist; /* Used only with Voronoi diagram; out only */ int numberofedges; /* Out only */ };
triangle.c:19 - #define REAL double
domingo, 3 de março de 13
A estrutura é bem compreensível e descritiva (supondo que você conheça o domínio). Os tipos de dados também. A única coisa pouco familiar é “REAL” — que, olhando no código, é apenas um double.
![Page 41: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/41.jpg)
Vamos começar definindo nosso encapsulamento com FFI.
domingo, 3 de março de 13
![Page 42: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/42.jpg)
require 'ffi' module Mesherator module TriangleFFI extend FFI::Library ffi_lib 'libtriangle'
typedef :pointer, :triangulateio attach_function :triangulate, [:string, :triangulateio, :triangulateio, :triangulateio], :void attach_function :trifree, [:pointer], :void endend
domingo, 3 de março de 13
Aqui defino então as duas funções. “attach_function” procura uma função de mesmo nome na biblioteca definida em “ffi_lib”. Os valores no array são os tipos de dados que a funcão recebe; o último argumento é o retorno. Como ambas não retornam nada (operam diretamente em ponteiros passados para elas), declaro como :void.
![Page 43: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/43.jpg)
Uma struct básica é mapeada com FFI::Struct.
domingo, 3 de março de 13
![Page 44: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/44.jpg)
class TriangulateIO < ::FFI::Struct layout :pointlist, :pointer, :pointattributelist, :pointer, :pointmarkerlist, :pointer, :numberofpoints, :int, :numberofpointattributes, :int, :trianglelist, :pointer, :triangleattributelist, :pointer, :trianglearealist, :pointer, :neighborlist, :pointer, :numberoftriangles, :int, :numberofcorners, :int, :numberoftriangleattributes, :int, :segmentlist, :pointer, :segmentmarkerlist, :pointer, :numberofsegments, :int, :holelist, :pointer, :numberofholes, :int, :regionlist, :pointer, :numberofregions, :int, :edgelist, :pointer, :edgemarkerlist, :pointer, :normlist, :pointer, :numberofedges, :intend
Todo ponteiro (*) vira :pointer
domingo, 3 de março de 13
Então eis a estrutura análoga em Ruby. Mantive os mesmos nomes, exatamente, para facilitar o entendimento, mas não é obrigatório: o mais importante é manter a ordem dos tipos de dados.
![Page 45: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/45.jpg)
layout garante que o bloco de memória criado em C se encaixará como uma luva.
domingo, 3 de março de 13
Se a ordem e os tipos forem mantidos, isso significa que quando eu falar em “pointlist” no Ruby, estarei acessando o pedacinho de memória que se refere a “pointlist” no C.
![Page 46: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/46.jpg)
E agora, uma classe em Ruby arrematando a parada toda.
domingo, 3 de março de 13
![Page 47: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/47.jpg)
class DelaunayTriangulator attr_reader :points def initialize(points) @points = points end
def triangulate point_array_ptr = FFI::MemoryPointer.new(:double, points.size * 2) point_array_ptr.write_array_of_double(flatten(points))
input = TriangulateIO.new output = TriangulateIO.new
input[:pointlist] = point_array_ptr input[:numberofpoints] = points.size input[:numberofpointattributes] = 0
TriangleFFI.triangulate 'czeXQ', input, output, nil
read_triangles_from output ensure free input free output end
# ...end
domingo, 3 de março de 13
![Page 48: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/48.jpg)
point_array_ptr = FFI::MemoryPointer.new(:double, points.size * 2)point_array_ptr.write_array_of_double(flatten(points))
input[:pointlist] = point_array_ptrinput[:numberofpoints] = points.sizeinput[:numberofpointattributes] = 0
# ...
# ...
# ...Libera toda memória alocada em Ruby no próximo ciclo de
GC, a não ser que você especifique algo diferente.
domingo, 3 de março de 13
Aqui acontece a única parte bem FFI mesmo: eu tenho que alocar um ponteiro que receberá meu array de pontos para passar ao C, e preciso colocar isso no meu TriangulateIO em “input”.
![Page 49: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/49.jpg)
# ... ensure free input free output end
Como há memória alocada no C, eu tenho que liberá-la.
domingo, 3 de março de 13
Como a biblioteca estipula que eu tenho que liberar toda a memória que o algoritmo por ventura alocar, adiciono um bloco ensure no final que chama DelaunayTriangulator#free em ambas as structs e cuida disso. Existe outra técnica (via ManagedStruct) que eliminaria esta seção.
![Page 50: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/50.jpg)
def read_triangles_from(triangulateio) triangle_count = triangulateio[:numberoftriangles] triangle_indices = triangulateio[:trianglelist].read_array_of_int(triangle_count * 3)
triangles = []
0.step(triangle_indices.size - 1, 3) do |first_point_index| p0 = points[triangle_indices[first_point_index]] p1 = points[triangle_indices[first_point_index + 1]] p2 = points[triangle_indices[first_point_index + 2]] triangles << Triangle.new(p0, p1, p2) end
trianglesend
domingo, 3 de março de 13
Aqui transformo os triângulos em “output” em instâncias de Triangle dentro do meu domínio. “trianglelist” é uma lista de índices apontado para o array original de pontos.
![Page 51: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/51.jpg)
Não dói muito, e você só precisa saber um tiquinho de C.
domingo, 3 de março de 13
É tranquilo. Você precisa saber o que é um ponteiro e que cada biblioteca tem alguma particularidade no gerenciamento de memória (apesar de, no C, haver um quase consenso de que quem usa uma biblioteca aloca e libera os buffers necessários/criados).
![Page 52: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/52.jpg)
DEMO
domingo, 3 de março de 13
![Page 53: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/53.jpg)
@dodecaphonic
domingo, 3 de março de 13
É isso. Obrigado pela atenção, e espero que tenha sido útil de alguma maneira.
![Page 54: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/54.jpg)
PERGUNTAS
domingo, 3 de março de 13
![Page 55: FFI - História, performance e felicidade com Ruby](https://reader033.vdocuments.net/reader033/viewer/2022042715/559bfc481a28ab4e668b46ef/html5/thumbnails/55.jpg)
http://github.com/dodecaphonic/mesherator
http://www.cs.cmu.edu/~quake/triangle.html
http://en.wikipedia.org/wiki/Delaunay_triangulation
domingo, 3 de março de 13