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:
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:
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#
| Forma | Para que serve |
|---|---|
asm … end | assembly, com a moldura de pilha controlável |
llvm … end | LLVM IR à mão, transparente ao otimizador |
cpp / cpp_region | uma 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.