VC ++ risorse in una libreria statica
-
22-08-2019 - |
Domanda
E 'possibile costruire le risorse in una libreria statica e riutilizzarli semplicemente collegando con la libreria?
Sono principalmente pensando al caso in cui si chiama una funzione nella libreria che a sua volta accede alle risorse.
Soluzione
Si può fare, ma è molto doloroso:. Non puoi farlo semplicemente collegando con la libreria statica
Considerate questo: risorse sono incorporati in un file EXE o DLL. Quando alcuni di codice nelle chiamate di libreria statica (ad esempio) LoadIcon, otterrà le risorse dal file EXE o DLL che è collegato con.
Quindi, se la libreria statica richiede risorse per essere a disposizione, hai un paio di opzioni:
- È possibile avere la libreria li costruire al volo, e quindi utilizzare (per esempio)
CreateDialogIndirect
. Vedi rel="noreferrer"> Raymond Chen . - È possibile averli incorporati nella libreria di array come semplici (cioè)
char my_dialog_resource[] = { .... };
, e quindi utilizzare (per esempio)CreateDialogIndirect
. Avrete probabilmente bisogno di trovare (o scrivere) un programma di utilità che converte i file da.RES
a.CPP
file. - È possibile spedire il file LIB con uno script di risorsa (file
.RC
) e corrispondenti file di intestazione. È quindi#include
loro come rilevante. Avrete bisogno di riservare un intervallo di ID di risorsa per il LIB da usare, in modo che non si scontrano con quelle del file EXE principale o DLL. Questo è ciò che fa MFC quando viene utilizzato come una libreria statica. Oppure è possibile utilizzare gli ID di risorsa di stringa (questo non funziona per le risorseSTRINGTABLE
). - Il tuo libreria statica può spedire con una DLL di risorse separato.
Altri suggerimenti
L'unica cosa che devi fare per utilizzare le risorse (immagini, finestre di dialogo, ecc ...) in una libreria statica in Visual C ++ (2008), è include file .res associate della libreria statica nel progetto. Questo può essere fatto in "Impostazioni del progetto / Linker / Input / dipendenze aggiuntive".
Con questa soluzione, le risorse della libreria statica sono imballati nel exe, in modo che non hanno bisogno di una DLL in più. Purtroppo, Visual Studio non include il file automaticamente i .res come avviene per il file LIB (quando si utilizzano le "dipendenze progetto" -feature), ma penso che questo piccolo passo in più è accettabile.
Ho cercato per un tempo molto lungo per questa soluzione, e ora mi sorprende è così semplice. L'unico problema è che è completamente documentato.
Ho appena passato attraverso questo con MS Visual Studio compilatore. Siamo stati convertendo alcuni progetti legacy da DLL in librerie statiche. Molte di queste DLL avevano risorse di dialogo o stringa incorporati in essi. Sono stato in grado di compilare gli script .RC per queste DLL nella nostra applicazione principale includendoli nel file di script RC dell'applicazione principale attraverso il meccanismo "TEXTINCLUDE". Ho trovato più semplice per farlo modificando direttamente il file RC, ma Visual Studio fornisce un meccanismo un po 'più "wizardy" pure. L'implementazione è più probabile diversa in altri compilatori.
Per manipolare direttamente lo script RC principale:
0,1. Nella sezione "2 TEXTINCLUDE", includere il file di intestazione che definisce gli ID di risorsa per la vostra biblioteca. La sintassi è
2 TEXTINCLUDE
BEGIN
"#include ""my_first_lib_header.h""\r\n"
"#include ""my_second_lib_header.h""\0"
END
0,2. Nella sezione "3 TEXTINCLUDE", includere lo script RC dalla libreria.
3 TEXTINCLUDE
BEGIN
"#include ""my_first_library.rc""\r\n"
"#include ""my_second_library.rc""\0"
END
i punti 3 e 4 dovrebbe avvenire automaticamente, ma ho trovato che fosse più affidabile di entrare solo io stesso, piuttosto che a seconda del compilatore di script di risorse di Microsoft per prendersi cura delle cose.
0,3. Aggiungere il file di intestazione con le librerie di risorse definisce alla lista solo simboli leggere. Questo elenco è di solito vicino alla parte superiore del file.
#define APSTUDIO_READONLY_SYMBOLS
#include "my_first_lib_header.h"
#include "my_second_lib_header.h"
#undef APSTUDIO_READONLY_SYMBOLS
0,4. Includere lo script RC della tua biblioteca nella sezione APSTUDIO_INVOKED. Questo è di solito nella parte inferiore del file.
#ifndef APSTUDIO_INVOKED
#include "my_first_library.rc"
#include "my_second_library.rc"
#endif
È anche possibile fare tutto questo automaticamente attraverso lo studio IDE visivo, ma ho trovato non si applica sempre quando mi aspettavo che.
- Aprire la finestra "Visualizzazione risorse" in Visual Studio.
- Fare clic destro sul file di risorse dell'applicazione principale e scegliere "Inclusioni risorsa ..." dal menu contestuale.
- Nella casella "direttive simbolo di sola lettura", aggiungere l'istruzioni include per i file .h che definiscono l'ID di risorsa di per le vostre librerie. "Direttive in fase di compilazione,"
- Nella casella Aggiungi il comprendono dichiarazioni per lo script RC della tua biblioteca.
- Fare clic a posto. Si consiglia inoltre di attivare manualmente la compilazione di script RC, per assicurarsi che succede.
Se script di risorse della tua biblioteca fa riferimento a tutti i file su disco (file di testo, file di icone, etc.), è necessario fare in modo che il progetto di applicazione principale sa dove trovarli. o È possibile copiare i file da qualche parte l'applicazione li può trovare o è possibile aggiungere un ulteriore percorso di inclusione nelle impostazioni del compilatore.
Per aggiungere un ulteriore percorso di inclusione:
- Aprire la finestra delle proprietà per la vostra applicazione principale.
- Selezionare "Proprietà di configurazione / Resources / General" dal riquadro di navigazione a sinistra.
- Nell'elenco proprietà, Invio eventuali percorsi pertinenti accanto a "Directory di inclusione aggiuntive."
Non penso così. libreria statica non ha di essa la propria HINSTANCE. E 'il codice viene eseguito nel contesto di DLL o EXE che lo collega. Ecco perché tutte le risorse che proveranno a caricare dal codice della libreria statica sarà di che racchiude DLL / EXE.
L'ho fatto quel tipo di risorse riutilizzare con una DLL, però, per quanto ha il proprio spazio di indirizzamento, ed è possibile chiamare LoadResource con HINSTANCE della DLL.
Come per Visual Studio 2010, gli strumenti di sviluppo di Microsoft a quanto pare non può gestire correttamente compilati i dati delle risorse all'interno di librerie statiche a tutti.
Per distribuire un file di risorse compilati (un file .res
), si hanno due scelte:
- Distribuire i file
.res
separatamente, e istruire il codice del client di collegare contro di loro; - Usa
cvtres
per unire più file.res
in un file unico oggetto (.obj
), e fornire separatamente.
Si noti che non è possibile Lib nel file oggetto creato con cvtres
. Se sono previste più file oggetto, lib
si lamenta come se sono stati dati come file multipli .res
; se viene fornito un file singolo oggetto, lib
non si lamenta, ma il linker semplicemente ignora i dati risorsa incorporata nel file lib.
Potrebbe essere il caso che ci sia un modo per forzare il linker a leggere e collegare l'improvvisato nei dati delle risorse (con qualche opzione da riga di comando, la sezione di manipolazione e così via), in quanto i dati delle risorse è infatti disponibile in biblioteca (come dumpbin
rivela). Finora, non ho trovato una soluzione, e, a meno che non si è disposti a incidere gli strumenti di sviluppo, niente di meglio di questa semplice soluzione è probabilmente non vale la pena.
L'unico modo per spedire i dati delle risorse in una libreria statica (in questo caso, con una libreria statica) è per distribuire le risorse separatamente e in modo esplicito collegarli nel codice client. Utilizzando cvtres
può ridurre il numero di file di risorse distribuite a uno, se si dispone di molti di loro.
Il metodo consigliato è quello di fornire una DLL con le risorse insieme con la libreria.
Quando viene utilizzato il seguente metodo, qualsiasi risorsa (in questo esempio, un'icona) può essere utilizzato come parte integrante di una libreria statica e tale libreria può essere utilizzato per qualsiasi tipo di applicazione, tra cui una consolle uno (che doesn 't hanno tutto il segmento delle risorse di sorta).
- icona viene convertito in un array statico di BYTE. bin2c può essere usato per questo.
-
I dati vengono convertiti in un manico HICON. Ecco come ho fatto che:
HICON GetIcon() { DWORD dwTmp; int offset; HANDLE hFile; HICON hIcon = NULL; offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR); if (offset != 0) { hIcon = CreateIconFromResourceEx(s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); } return hIcon; }
-
GetIcon viene usato al posto di LoadIcon. Invece di chiamare:
m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIcon));
Quindi chiamare
m_hIcon = GetIcon()