Overriding @executable_path in una DLL caricata con dlopen ()
-
28-10-2019 - |
Domanda
Il sistema operativo è macOS X, in particolare 10.5 (leopardo) su un powerPC G4, ma ho lo stesso problema su un X86 in esecuzione 10.6.
Sto scrivendo un'applicazione che carica dinamicamente una DLL. La DLL (chiamiamolo foo.dylib
) fa parte di un'altra applicazione, situata altrove sul harddisk; La mia applicazione trova foo.dylib
programmaticamente (la collocazione esatta può cambiare, possibilmente l'utente designa il percorso DLL attraverso una GUI dall'applicazione in esecuzione stessa). Ad esempio, supponiamo che la mia domanda si trovi nella directory /Application/MyApp.app/Contents/MacOS
, e foo.dylib
capita di essere /Application/OtherApp.app/Contents/MacOS
. Usi di caricamento DLL dlopen()
.
Ora, si scopre foo.dylib
stesso ha bisogno di un mucchio di altre DLL, che sono nella stessa directory, ma di cui non so nulla in anticipo. Ogni DLL extra è registrata in foo.dylib
con un percorso come @executable_path/bar.dylib
. La semantica di @executable_path
sono che dovrebbe essere sostituito dalla directory in cui è stato trovato l'eseguibile del processo corrente. Funziona alla grande per altropp, non per me: quando apro foo.dylib
, cerca di caricare bar.dylib
, e lo cerca dentro /Application/MyApp.app/Contents/MacOS/bar.dylib
, che non è la directory giusta.
Una soluzione alternativa è impostare il DYLD_FALLBACK_LIBRARY_PATH
Ambiente variabile a /Application/OtherApp.app/Contents/MacOS
, ma questo deve essere fatto prima Avvio della mia applicazione (quella variabile di ambiente è lettura solo una volta dal linker dinamico; modificando il suo valore programmaticamente con setenv()
o putenv()
non ha alcun effetto). Questo non è compatibile con la scoperta dinamica della posizione del foo.dylib
file.
Esiste un modo programmatico per sovrascrivere l'effetto di @executable_path
?
Soluzione
Dalla lettura del fonte dyld (Cerca @executable_path), direi che la risposta è inequivocabilmente "no". @Executable_Path viene sostituito con il percorso eseguibile principale, che viene archiviato come una stringa globale nel modulo Dyld.
E sì, il tuo sospetto è corretto, Dyld legge e salva le sue variabili di ambiente all'avvio, quindi non puoi cambiarle al volo (puoi cercare lo stesso file di origine che ho collegato per Dyld_Library_Path). Potresti avere un'applicazione stub che imposta le variabili di ambiente e quindi lancia la tua vera applicazione. Dyld non ti offre molte soluzioni qui, non è davvero progettato per consentirti di collegare in librerie arbitrarie di terze parti private.
Altri suggerimenti
Se mantieni altro, è possibile utilizzare @Loader_Path invece di @Executable_Path per individuare le dipendenze: @loader_Path Risolvi sempre sul percorso del modulo (IE libreria o eseguibile) che richiede di caricare la libreria, quindi le dipendenze ricorsive si trovano sempre.
Questo è disponibile da Mac OS 10.5 in poi.
Vedi "Man Dyld" per informazioni dettagliate.
Un'altra opzione sarebbe dlopen
dipendenze prima della biblioteca principale.