Fenner
A linguagem

Interoperabilidade

DLLs e a API do Windows, library e exports, COM, assembly, LLVM IR e C++ dentro do fonte.

Chamando DLLs e a API do Windows#

Uma rotina external importa uma função de uma DLL, por nome ou por ordinal:

Fenner
function GetTickCount: UInt32; stdcall; external 'kernel32.dll' name 'GetTickCount';
function PorOrdinal(A: UInt32): Bool32; external 'user32.dll' index 5;

A convenção de chamada (stdcall, cdecl, register, safecall, pascal) é escrita na declaração, e a ABI pode ser forçada (abi_win, abi_posix). Os módulos da RTL já trazem a API do Windows pronta (Kernel32, User32, ActiveX, CommCtrl, RichEdit, ShlObj…).

Criando uma DLL#

Um projeto library gera uma DLL. O corpo begin … end. roda quando a DLL é carregada (DllMain), e a cláusula exports publica os símbolos:

lib-greeter.fxp
library Greeter;

// Uma biblioteca vira uma DLL; a cláusula exports publica os símbolos.

function Add(A, B: Int32): Int32; stdcall;
begin
  Exit(A + B);
end function;

function Square(A: Int32): Int32; stdcall;
begin
  Exit(A * A);
end function;

exports
  Add,
  Square name 'SquareRenamed';

begin
  // roda quando a DLL é carregada (aqui, nada a fazer)
end.

Quem consome a DLL a importa com external. Dentro dela, classes e exceções vivem normalmente: um objeto criado e uma exceção capturada do mesmo lado funcionam, e a RTL de cada binário é a sua, a menos que você use o runtime compartilhado.

Um package#

Um package é a forma de uma DLL cujos tipos (classes, records, interfaces, genéricos) atravessam a fronteira: o cliente recebe o .fxd e o compilador resolve tudo sozinho. Veja Packages e o .fxd.

COM#

A RTL traz as interfaces de COM (IUnknown, IStream, IDispatch…) com a ABI própria, o WString como BSTR de verdade e o OleVariant. Uma classe implementa uma interface de COM como implementa qualquer outra. Alguns pontos de interoperabilidade com COM ainda estão em andamento.

Código de baixo nível no fonte#

FormaPara que serve
asm … endassembly, com a moldura de pilha controlável
llvm … endLLVM IR à mão, transparente ao otimizador
cpp / cpp_regionuma sub-linguagem C++ traduzida para o Pascal da casa

Esses blocos existem para o que a linguagem não diz: instruções especiais da CPU, um laço quente escrito à mão, o porte de um trecho de C++.

Bibliotecas de objetos#

{$ObjLink 'arquivo.lib'} entrega uma .lib ao ligador, que extrai só os membros citados. É assim que a RTL BedRock embute o OpenSSL, o zlib, o pcre2, o SQLite e o 7-Zip sem precisar de DLL ao lado. Uma rotina external sem nome de DLL (cdecl; external;) liga contra símbolos dessas bibliotecas.

Plataformas#

O alvo é escolhido por -P<plataforma> (MSWin64, MSWin32, Linux64) e define símbolos que o código pode testar com {$ifdef}. A fachada POSIX da RTL (Sys*) dá o mesmo contrato nas duas famílias de plataforma. Veja Plataformas e modos para o estado de cada uma.