Use qmake para construir uma estrutura para carregar bibliotecas estáticas e compartilhadas

índice

1. Estabelecer um projeto de grande escala

1.1 Construir uma biblioteca estática

1.2 Criar uma biblioteca compartilhada

Dois, chame o arquivo de biblioteca gerado

Três, carregar bibliotecas compartilhadas em tempo de execução

Sobre o plugin

Sobre embalagem


 

Para a sintaxe do qmake, consulte: http://doc.qt.io/qt-5/qmake-manual.html . Este é qt5 e qt4 e qt5 são escritos de forma ligeiramente diferente.

De um modo geral, os projetos que construímos usando qt creator terminam com .pro, na verdade, o que está envolvido aqui é a sintaxe qmake.

Além dos arquivos .pro, existem arquivos .pri, .prf e .prl.

  • Não há muito a dizer sobre o pro arquivo.
  • O i em pri é a primeira letra de i nclude. É semelhante aos arquivos de cabeçalho em C e C ++. De qualquer forma, podemos colocar uma parte do arquivo * .pro em um arquivo * .pri e depois incluí-lo.
  • O prf f é a característica ( f atura semelhante) do primeiro caractere, e o arquivo pri deve ser incluído no pro arquivo como CONFIG + = QT.

  • ls link prl de ( L Ink) do primeiro caractere. Está principalmente relacionado à geração e uso de bibliotecas estáticas (bibliotecas dinâmicas também podem ter esse arquivo, basta ir ao diretório lib no diretório de instalação do Qt para dar uma olhada).

Para obter detalhes, consulte a postagem do blog " Nos arquivos pro, pri, prf e prl do qmake ".

Portanto, qmake é particularmente importante para construir um projeto de grande escala.

Este artigo refere-se a postagens de blog: " Qt para criar e usar bibliotecas compartilhadas ", " Qt para carregar bibliotecas compartilhadas em tempo de execução " e " Qt para criar e usar bibliotecas de link estático ".

 

1. Estabelecer um projeto de grande escala

Escolha primeiro criar um novo projeto, clique em outros projetos, selecione o subdiretório projeto e, a seguir, selecione o caminho e nomeie-o.

O arquivo .pro gerado neste momento deve ser o seguinte:

TEMPLATE = subdirs
CONFIG += ordered

Em seguida, crie diferentes subprojetos no projeto, que podem ser programas executáveis ​​ou arquivos de biblioteca. Clique com o botão direito para criar um novo "novo subprojeto".

Por exemplo, crie um novo projeto de biblioteca aqui e entre na próxima etapa após a seleção:

Aqui você pode escolher construir uma biblioteca compartilhada, uma biblioteca estática ou um plugin Qt (plugin Qt).

1.1 Construir uma biblioteca estática

Opte por criar uma biblioteca estática. Neste momento, o arquivo .pro do subprojeto deve conter o seguinte:

TARGET = staticLib
TEMPLATE = lib
CONFIG += staticlib

Indica que uma biblioteca estática chamada staticLib será gerada.

Adicione mais algumas linhas abaixo:

CONFIG += debug_and_release
CONFIG(debug, debug|release): TARGET = $$join(TARGET,,,d)
DESTDIR = ../../externlib/

Indica que o arquivo de biblioteca gerado será colocado em externlib e, se for compilado para depuração, d será adicionado ao sufixo gerado.

Para arquivos .h e .cpp, você pode escrever várias funções livremente.

1.2 Criar uma biblioteca compartilhada

O processo de criação de uma biblioteca compartilhada é igual ao de uma biblioteca estática, mas a seleção é diferente. Neste momento, o arquivo .pro deve ser o seguinte:

TARGET = sharedLib
TEMPLATE = lib
DEFINES += SHAREDLIB_LIBRARY

Indica que uma biblioteca compartilhada chamada sharedLib será gerada.

Como a biblioteca compartilhada precisa ser colocada no mesmo diretório do programa executável, as seguintes linhas precisam ser adicionadas:

CONFIG += debug_and_release
CONFIG(debug, debug|release): TARGET = $$join(TARGET,,,d)
CONFIG(debug, release|debug): DESTDIR = ../../debug/
CONFIG(release, release|debug): DESTDIR = ../../release/

Da mesma forma, aqui d é adicionado ao sufixo compilado na versão de depuração.

Para arquivos .h e .cpp, você pode escrever interfaces de função livremente.

Além dos dois arquivos de classes C ++ gerais, o Qt Creator também nos ajudará a criar um arquivo de cabeçalho chamado {projectName} _global.h para garantir que a macro correta possa ser chamada.

Além disso, se estiver escrito na linguagem C, você também precisará adicionar extern "C" no arquivo de cabeçalho exportado.

 

Dois, chame o arquivo de biblioteca gerado

Primeiro crie um novo subprojeto, selecione Aplicativo para gerar arquivos executáveis.

Da mesma forma, para o arquivo final gerado, atribuímos ao diretório de recursos.Geralmente, o software terá uma versão de depuração e uma versão de lançamento para distinção, e também adicionará o seguinte código.

CONFIG(debug, release|debug): DESTDIR = ../../debug/
CONFIG(release, release|debug): DESTDIR = ../../release/

Escrever dessa maneira é um bom hábito para separar efetivamente o rel gerado pelo debug.

Em seguida, no subprojeto, clique com o botão direito para adicionar a biblioteca. Como os projetos de biblioteca compartilhada de biblioteca estática criados antes estão todos no mesmo projeto, você pode selecionar a biblioteca interna.

O nome da biblioteca a ser selecionada pode ser reconhecido automaticamente, a plataforma pode ser verificada e a versão de depuração é adicionada com 'como sufixo.

Depois de adicionar, as seguintes linhas serão adicionadas automaticamente ao arquivo .pro:

win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../externlib/ -lstaticLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../externlib/ -lstaticLibd
else:unix: LIBS += -L$$OUT_PWD/../../externlib/ -lstaticLib

INCLUDEPATH += $$PWD/../staticLib
DEPENDPATH += $$PWD/../staticLib

win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../externlib/libstaticLib.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../externlib/libstaticLibd.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../externlib/staticLib.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../externlib/staticLibd.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../../externlib/libstaticLib.a

Parece muito complicado e na verdade é semelhante a adicionar dependências em um projeto do VS, incluindo o diretório onde os arquivos de cabeçalho estão localizados. Observe que o arquivo de biblioteca estática precisa ser atribuído à pasta externlib , correspondendo à construção anterior.

Da mesma forma, o processo de adicionar bibliotecas compartilhadas é o mesmo. Depois de adicionar, o seguinte será adicionado ao arquivo .pro:

win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../release/ -lsharedLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../debug/ -lsharedLibd
else:unix: LIBS += -L$$OUT_PWD/../sharedLib/ -lsharedLib

INCLUDEPATH += $$PWD/../sharedLib
DEPENDPATH += $$PWD/../sharedLib

É basicamente o mesmo que adicionar uma biblioteca estática.

 

Em relação às bibliotecas estáticas e às bibliotecas compartilhadas, ambos os arquivos .lib são necessários durante a compilação. Após a compilação, os arquivos dll ou mais da biblioteca compartilhada devem ser colocados em um local onde o arquivo executável possa ser encontrado, caso contrário, o tempo de execução avisará que a dependência está faltando e a biblioteca estática é necessária em tempo de compilação. As vantagens e desvantagens específicas são as seguintes:

  • Ao criar uma biblioteca compartilhada, ela precisa ser implementada em um aplicativo.Os aplicativos e bibliotecas associadas à biblioteca compartilhada são muito pequenos.
  • A ligação estática irá gerar um arquivo executável independente. A vantagem disso é que apenas alguns arquivos precisam ser implantados. A desvantagem é que o arquivo executável se tornará muito grande.

Após a implantação acima, podemos chamar a interface de função na biblioteca estática ou biblioteca compartilhada.

 

Três, carregar bibliotecas compartilhadas em tempo de execução

O primeiro e o segundo acima de tudo falam sobre como implantar em um projeto completo enquanto depende de arquivos de biblioteca. Na verdade, outra vantagem do arquivo de biblioteca compartilhada é escolher se deseja carregar ou não quando o programa inicia, ou seja, o modo de plug-in que costumamos chamar.

Qt sugere a biblioteca QLibrary ou QPluginLoader duas maneiras de carregar bibliotecas compartilhadas.

Se você usar a classe QLibrary, a função resolver é geralmente usada. Para obter detalhes, consulte " Qt: Carregando bibliotecas compartilhadas em tempo de execução ".

Se você usa o QtPlugin, precisa adicionar as seguintes linhas:

#define PluginID   "org.qt-project.Qt.Examples.plugin.IPluginUi"
Q_DECLARE_INTERFACE(IPluginUi, PluginID)

Q_PLUGIN_METADATA(IID PluginID FILE "pluginForm.json")
Q_INTERFACES(IPluginUi)

O arquivo json é usado para descrever algumas propriedades do plug-in.

O código-chave do método de chamada específico do QtPlugin é o seguinte:

QStringList filters;
filters << "*.dll" << "*.so";      //在插件所在的文件夹下筛选后缀为dll或so结尾的文件
pluginDir.setNameFilters(filters);
foreach (QString filename, pluginDir.entryList(QDir::Files))
{
	QPluginLoader *pluginload = new QPluginLoader(pluginDir.absoluteFilePath(filename));
	pluginload->setLoadHints(QLibrary::ExportExternalSymbolsHint | QLibrary::ResolveAllSymbolsHint);
	if(pluginload->load())
	{
		QObject *obj = pluginload->instance();
		if(obj)
		{
			IPluginUi *plugin = qobject_cast<IPluginUi*>(obj);
			if(plugin)
			{
				QWidget *widget = plugin->PluginUi();
				QString str_sn = plugin->getSerialNumber();

				QString class_name = pluginload->metaData().value("className").toString();
				ui->textEdit->append("export class: " + class_name);
				QJsonObject json = pluginload->metaData().value("MetaData").toObject();
				QString str_author = json.value("author").toString();
				QString str_date = json.value("date").toString();
				QString str_license = json.value("license").toString();
				QString str_version = json.value("version").toString();
				QJsonArray array = json.value("changelog").toArray();
			}
		}
	}
}

Desde então, o plug-in foi carregado.

O efeito de demonstração para uma demonstração é o seguinte:

A interface do plug-in carregado será exibida na Tab2.

O código completo do projeto pode ser encontrado em https://github.com/WelinLee/qt_pattern , e pode ser compilado nas plataformas Windows e Linux.

 

Sobre o plugin

Por meio do acima, podemos projetar um pequeno programa de plug-in. Ao projetar esse programa modular, os seguintes pontos devem ser considerados:

  • Como registrar o plugin;
  • Como chamar o plug-in;
  • Como testar o plug-in;
  • Gerenciamento do ciclo de vida do plug-in;
  • Forneça informações como nome, versão e status do plug-in, obtenha a lista de plug-ins, registre o log de processamento do plug-in, etc .;
  • Tratamento de erros de plug-in.

Para obter detalhes, consulte "Conhecimento aprofundado do sistema de plug-in " e " Construindo seu próprio sistema de plug-in Qt ".

 

Sobre embalagem

Para a geração do software, se for plataforma windows pode ser usado windeploy qt .exe empacotado.

No Linux, você pode usar o comando ldd (deplist = $ (ldd $ exe | awk '{if (match ($ 3, "/")) {printf ("% s", $ 3)}}')) para encontrar o que o programa precisa de dependências e, em seguida, empacota-as.

 

Acho que você gosta

Origin blog.csdn.net/u014610460/article/details/84928321
Recomendado
Clasificación