Pergunta

É possível recursos construir em uma biblioteca estática e reutilizá-los, basta ligar com a biblioteca?

Estou pensando principalmente sobre o caso em que você chamar uma função na biblioteca que por sua vez acessa recursos.

Foi útil?

Solução

Pode ser feito, mas é muito doloroso:. Você não pode fazer isso, basta ligar com a biblioteca estática

Considere o seguinte: recursos são incorporados em um EXE ou DLL. Quando algum código nas chamadas de bibliotecas estáticas (por exemplo) LoadIcon, vai obter os recursos do EXE ou DLL que está ligado a.

Assim, se sua biblioteca estática requer recursos estejam disponíveis, você tem um par de opções:

  1. Você pode ter a construção da biblioteca los em tempo real, e então usar (por exemplo) CreateDialogIndirect. Veja de Raymond Chen "Construir um modelo de diálogo em tempo de execução" .
  2. Você pode tê-los incorporado na biblioteca como matrizes simples (ou seja) char my_dialog_resource[] = { .... };, e depois CreateDialogIndirect uso (por exemplo). Você provavelmente vai precisar de encontrar (ou escrever) um utilitário que converte a partir de arquivos .RES para arquivos .CPP.
  3. Você pode enviar o arquivo LIB com um script de recursos (arquivo .RC) e correspondente arquivo de cabeçalho. Você, então, #include-los como relevante. Você precisa reservar um intervalo de IDs de recursos para o LIB para uso, de modo que eles não colidir com os da EXE principal ou DLL. Isto é o que MFC faz quando usado como uma biblioteca estática. Ou você pode usar IDs de recursos de corda (isso não funciona para recursos STRINGTABLE).
  4. A sua biblioteca estática pode ser fornecido com um recurso DLL separada.

Outras dicas

A única coisa que você precisa fazer para usar os recursos (imagens, diálogos, etc ...) em uma biblioteca estática em Visual C ++ (2008), é incluem ficheiro.RES associado da biblioteca estática no seu projecto. Isso pode ser feito em "Configurações do projeto / Linker / input / dependências adicionais".

Com esta solução, os recursos da biblioteca estática são embalados para o .exe, para que você não precisa de uma DLL extra. Lamentavelmente, Visual Studio não inclui o arquivo res automaticamente como faz para o arquivo .lib (ao usar os "dependências do projeto" -feature), mas acho que este pequeno passo extra é aceitável.

Eu olhei para um tempo muito longo para esta solução, e agora me surpreende é tão simples. O único problema é que ele é totalmente documentado.

Eu só passei por isso com o compilador do Visual Studio MS. Nós estávamos convertendo alguns projetos legados de DLLs em bibliotecas estáticas. Várias dessas DLLs teve recursos de diálogo ou de cordas embutidos nelas. Eu era capaz de compilar os scripts .RC para essas DLLs em nosso aplicativo principal, incluindo-os no arquivo de script RC do aplicativo principal através do mecanismo de "TEXTINCLUDE". Eu achei mais fácil fazer isto editando o arquivo RC diretamente, mas Visual Studio fornece um mecanismo ligeiramente mais "wizardy" também. A implementação é mais provável diferente em outros compiladores.


Para manipular o script RC principal diretamente:

.1. Na seção "2 TEXTINCLUDE", inclua o arquivo de cabeçalho que define os IDs de recursos para a sua biblioteca. A sintaxe é

2 TEXTINCLUDE 
BEGIN
    "#include ""my_first_lib_header.h""\r\n"
    "#include ""my_second_lib_header.h""\0" 
END

.2. Na seção "3 TEXTINCLUDE", incluem o script RC da sua biblioteca.

3 TEXTINCLUDE
BEGIN
    "#include ""my_first_library.rc""\r\n"
    "#include ""my_second_library.rc""\0"
END

Passos 3 e 4 deve acontecer automaticamente, mas eu achei que era mais confiável para apenas inseri-los eu mesmo, em vez de depender do compilador script de recursos da Microsoft para cuidar das coisas.

0,3. Adicione o arquivo de cabeçalho com as suas bibliotecas define recursos para a lista apenas símbolos ler. Esta lista é geralmente perto do topo do arquivo.

#define APSTUDIO_READONLY_SYMBOLS
#include "my_first_lib_header.h"
#include "my_second_lib_header.h"
#undef APSTUDIO_READONLY_SYMBOLS

0,4. Incluir roteiro RC da sua biblioteca na seção APSTUDIO_INVOKED. Este é geralmente na parte inferior do arquivo.

#ifndef APSTUDIO_INVOKED
#include "my_first_library.rc"
#include "my_second_library.rc"
#endif 

Você também pode fazer tudo isso automaticamente através do IDE Visual Studio, mas eu achei que nem sempre se aplicam quando eu esperava que.

  1. Abra a "exibição de recurso" janela no Visual Studio.
  2. botão direito do mouse no arquivo de recurso a sua principal do aplicativo e escolha "inclui recursos ..." no menu de contexto.
  3. Na caixa intitulada "read-only directivas símbolo", adicione a incluir declarações para os arquivos .h que definem o ID do recurso é para as suas bibliotecas.
  4. Na caixa "directivas tempo de compilação," adicionar a incluir declarações para o script rc da sua biblioteca.
  5. Clique em OK. Você também pode querer disparar manualmente a compilação de script RC, para se certificar de que isso acontece.

Se referências de script de recursos da sua biblioteca quaisquer arquivos no disco (arquivos de texto, ícones, etc.), você precisa ter certeza de que o projeto principal da aplicação sabe onde encontrá-los. Você qualquer um pode copiar esses arquivos para algum lugar de sua aplicação pode encontrá-los ou você pode adicionar um caminho de inclusão adicional nas configurações do compilador.

Para adicionar um caminho de inclusão adicional:

  1. Abra a caixa de diálogo Propriedades para a sua aplicação principal.
  2. Seleccione "Configuração Propriedades / Resources / General" do painel de navegação do lado esquerdo.
  3. Na lista de propriedades, insira quaisquer caminhos pertinentes ao lado de "Incluir adicionais Diretórios".

Eu não penso assim. biblioteca estática não tem o seu próprio HINSTANCE. É o código é executado no contexto do DLL ou EXE que liga-lo. É por isso que todos os recursos que você vai tentar carregar a partir do código da biblioteca estática será de que anexando DLL / EXE.

Eu fiz esse tipo de recursos reutilizar com um DLL no entanto, na medida em que tem o seu espaço de endereço próprio, e você pode chamar LoadResource com HINSTANCE de DLL.

De acordo com o Visual Studio 2010, as ferramentas de desenvolvimento da Microsoft, aparentemente, não pode tratar adequadamente compilados dados de recursos dentro de bibliotecas estáticas em tudo.

Para distribuir um arquivo de recurso compilado (um arquivo .res), você tem duas opções:

  1. Distribuir os arquivos .res separadamente, e instruir o código de cliente para ligação contra eles;
  2. Use cvtres para mesclar vários arquivos .res em um único objeto (.obj) arquivo, e fornecê-lo separadamente.

Note que você não pode lib em arquivos objeto criado com cvtres. Se vários arquivos objeto são fornecidos, lib reclama como se como vários arquivos .res foram dadas; Se um único arquivo objeto é fornecido, lib não reclama, mas o linker simplesmente ignora os dados de recursos incorporados no arquivo lib.

Pode ser o caso de que existe uma maneira de forçar o vinculador para ler e vincular o libbed em dados de recursos (com alguma opção de linha de comando, seção de manipulação e assim por diante), desde que os dados de recursos é realmente disponível no biblioteca (como dumpbin revela). Até agora, eu não encontrei uma solução, e, a menos que um está disposto a cortar as ferramentas de desenvolvimento, nada melhor do que esta solução simples, não é provavelmente vale a pena o esforço.

A única maneira de dados de recursos navio em uma biblioteca estática (neste caso, com uma biblioteca estática) é distribuir os recursos separadamente e explicitamente ligá-los no código do cliente. Usando cvtres pode reduzir o número de arquivos de recursos distribuídos para um, se você tem muitos deles.

A maneira recomendada é fornecer uma dll com os recursos em conjunto com a sua biblioteca.

Quando o seguinte método é usado, qualquer recurso (neste exemplo, um ícone) pode ser usado como uma parte integrante de uma biblioteca estática e tal biblioteca pode ser usado por qualquer tipo de aplicação, incluindo um console (que doesn 't ter qualquer qualquer segmento de recursos).

  1. Ícone é convertido para uma matriz estática de BYTE. bin2c pode ser usado para isso.
  2. Os dados são convertidos em uma alça HICON. Aqui está como eu fiz isso:

    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;  
    }
    
  3. GetIcon é usado em vez de LoadIcon. Em vez de chamar:

m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIcon));

Em seguida, chamar

m_hIcon = GetIcon()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top