Em teoria android é arm linux, a compilação de um .so deve funcionar. A questão é fazer oque?
Para carregar a biblioteca criada no Lazarus em Kotlin/JVM, a solução mais simples é usar JNA (Java Native Access). Ela permite chamar diretamente as funções exportadas da DLL ou .so, sem criar uma camada JNI em C/C++.
1. Biblioteca Lazarus
A biblioteca Pascal pode permanecer assim:
library samplelibrary;
{$mode objfpc}{$H+}
uses
Classes,
SysUtils;
function Somar(A, B: Integer): Integer; cdecl;
begin
Result := A + B;
end;
function Multiplicar(A, B: Double): Double; cdecl;
begin
Result := A * B;
end;
procedure ObterVersao(Buffer: PChar; BufferSize: Integer); cdecl;
const
VERSAO = '1.0.0';
begin
if (Buffer = nil) or (BufferSize <= 0) then
Exit;
StrLCopy(Buffer, PChar(VERSAO), BufferSize - 1);
end;
exports
Somar name 'Somar',
Multiplicar name 'Multiplicar',
ObterVersao name 'ObterVersao';
begin
end.
Ela produzirá:
samplelibrary.dll
no Windows, ou:
libsamplelibrary.so
no Linux.
2. Dependência JNA no Kotlin
No build.gradle.kts:
plugins {
kotlin("jvm") version "2.2.0"
application
}
repositories {
mavenCentral()
}
dependencies {
implementation("net.java.dev.jna:jna:5.18.1")
}
application {
mainClass.set("MainKt")
}
A versão 5.18.1 é a versão publicada atualmente no Maven Central.
3. Interface Kotlin
Crie SampleLibrary.kt:
import com.sun.jna.Library
import com.sun.jna.Memory
import com.sun.jna.Native
import java.io.File
interface SampleLibrary : Library {
fun Somar(a: Int, b: Int): Int
fun Multiplicar(a: Double, b: Double): Double
fun ObterVersao(buffer: Memory, bufferSize: Int)
companion object {
fun load(libraryFile: String): SampleLibrary {
val file = File(libraryFile).absoluteFile
require(file.exists()) {
"Biblioteca não encontrada: ${file.absolutePath}"
}
return Native.load(
file.absolutePath,
SampleLibrary::class.java
)
}
}
}
O nome e a capitalização dos métodos Kotlin devem corresponder exatamente aos nomes exportados pela biblioteca:
Somar
Multiplicar
ObterVersao
4. Aplicação Kotlin completa
Crie Main.kt:
import com.sun.jna.Memory
import java.io.File
fun getLibraryPath(): String {
val operatingSystem = System
.getProperty("os.name")
.lowercase()
val applicationDirectory = File(
System.getProperty("user.dir")
)
val libraryName = when {
operatingSystem.contains("windows") ->
"samplelibrary.dll"
operatingSystem.contains("linux") ->
"libsamplelibrary.so"
operatingSystem.contains("mac") ->
"libsamplelibrary.dylib"
else ->
error("Sistema operacional não suportado: $operatingSystem")
}
return File(
applicationDirectory,
libraryName
).absolutePath
}
fun main() {
try {
val libraryPath = getLibraryPath()
println("Carregando biblioteca:")
println(libraryPath)
val library = SampleLibrary.load(libraryPath)
val soma = library.Somar(10, 20)
println("10 + 20 = $soma")
val multiplicacao = library.Multiplicar(5.5, 2.0)
println("5.5 × 2 = $multiplicacao")
val bufferSize = 256L
val buffer = Memory(bufferSize)
buffer.clear()
library.ObterVersao(
buffer,
bufferSize.toInt()
)
val versao = buffer.getString(0)
println("Versão da biblioteca: $versao")
} catch (exception: UnsatisfiedLinkError) {
System.err.println(
"Erro ao carregar a biblioteca nativa: " +
exception.message
)
exception.printStackTrace()
} catch (exception: Exception) {
System.err.println(
"Erro: ${exception.message}"
)
exception.printStackTrace()
}
}
5. Estrutura do projeto
kotlin-library-sample/
├── build.gradle.kts
├── settings.gradle.kts
├── samplelibrary.dll
└── src/
└── main/
└── kotlin/
├── Main.kt
└── SampleLibrary.kt
O settings.gradle.kts:
rootProject.name = "kotlin-library-sample"
No Linux:
kotlin-library-sample/
├── libsamplelibrary.so
├── build.gradle.kts
└── src/
6. Executando
No Windows:
.\gradlew.bat run
No Linux:
./gradlew run
Resultado esperado:
Carregando biblioteca:
C:\projetos\kotlin-library-sample\samplelibrary.dll
10 + 20 = 30
5.5 × 2 = 11.0
Versão da biblioteca: 1.0.0
7. Compatibilidade de arquitetura
A arquitetura da biblioteca precisa ser a mesma da JVM:
Biblioteca Lazarus Java/Kotlin
DLL Win32 JVM 32 bits
DLL Win64 JVM 64 bits
.so Linux x86_64 JVM Linux x86_64
.so Linux ARM64 JVM Linux ARM64
Para verificar a JVM:
fun main() {
println("Arquitetura: ${System.getProperty("os.arch")}")
println("JVM: ${System.getProperty("java.version")}")
}
Geralmente aparecerá:
Arquitetura: amd64
Nesse caso, a DLL deve ser compilada para Windows 64 bits.
8. Erros mais comuns
UnsatisfiedLinkError
Normalmente indica:
DLL não encontrada;
arquitetura incompatível;
dependência da DLL ausente;
nome da função exportada diferente;
tentativa de carregar DLL Windows no Linux.
Error looking up function
Significa que a função não foi exportada com o nome esperado. Confirme:
exports
Somar name 'Somar';
JVM encerra ao chamar a função
Normalmente é incompatibilidade na convenção de chamada ou nos tipos. Mantenha cdecl dos dois lados. No mapeamento usado:
Pascal Integer → Kotlin Int
Pascal Double → Kotlin Double
Pascal PChar → JNA Memory/Pointer
Essa implementação é adequada para Kotlin/JVM desktop. Em Android, a biblioteca precisaria ser compilada como .so para cada ABI, como arm64-v8a, e o empacotamento seria diferente.
Fonte GPT