Статическая библиотека Windows C ++ не может получить доступ к внешнему методу во время инициализации - PullRequest
1 голос
/ 08 ноября 2019

Я преобразую большое приложение Windows C ++ из большого набора исходных файлов в меньшее базовое приложение, связанное с несколькими статическими библиотеками (куда перемещаются многие исходные исходные файлы).

Каждая библиотека требуетдоступ к «методу регистрации» в основном приложении. Каждая библиотека должна вызывать этот метод во время глобальной инициализации, но этого не происходит. Это моя проблема.

Код отлично работает в исходном виде, где библиотеки не используются. Я предполагаю, что пропускаю необходимую опцию ссылки для библиотек, но я не знаю, какая.

Я создал минимальный, работоспособный пример. Я разработал это на Windows 10, используя:

CMake 3.14.5
MSVC 2019

Вот CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.9)
project (CMakeLinkTest)
add_library(myLibrary STATIC MyStar.cpp)
add_executable(CMakeLinkTest StarFactory.cpp main.cpp)
target_link_libraries(CMakeLinkTest myLibrary)

Приложение содержит main.cpp:

#include <iostream>

int main(int argc, char *argv[]){
   std::cout << "Hello World!" << std::endl;
   return 0;
}

и синглтонкласс под названием StarFactory.

StarFactory.h:

#include<string>

class StarFactory
{
public:

    static StarFactory* instance();
    ~StarFactory() {};

    std::string registerStarType(std::string a_type);

private:

    StarFactory() {};

    static StarFactory* mp_instance;   // Singleton instance 
};

StarFactory.cpp:

#include <iostream>
#include "StarFactory.h"

StarFactory* StarFactory::mp_instance = 0;

StarFactory* StarFactory::instance()
{
    if ( mp_instance==0 )
        mp_instance = new StarFactory;

    return mp_instance;
}

std::string StarFactory::registerStarType(std::string a_type)
{
    std::cout << "registerStarType: " << a_type << std::endl;
    return a_type;
}

Наконец, статическая библиотека содержит класс MyStar, который регистрируется с помощью singletonпри глобальной инициализации.

MyStar.cpp:

#include<string>
#include "StarFactory.h"

class MyStar
{
public:
    MyStar() {
        StarFactory* s = StarFactory::instance();
        //s->registerStarType("MyStar");
    };
};

MyStar myStar;
std::string starName = StarFactory::instance()->registerStarType("MyStar");

Теперь о том, что происходит. Если я связываю MyStar.cpp непосредственно с приложением, я вижу:

>CMakeLinkTest.exe
registerStarType: MyStar
Hello World!

Если я связываю MyStar.cpp с MyLibrary.lib и связываю это с приложением, я вижу:

>CMakeLinkTest.exe
Hello World!

вызов библиотеки (последняя строка MyStar.cpp) для синглтона приложения не работает.

Может кто-нибудь объяснить это, пожалуйста?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Поведение по умолчанию для компоновщика не включает статическую библиотеку, на которую нет ссылок.

Вы можете:

  • заставить компоновщик включить библиотекув любом случае - вы можете использовать add_link_options или эквивалентный * cmake
  • , не использовать статическую библиотеку - просто связать объект, как в первом примере
  • ссылаться на код в статической библиотеке
  • используйте взамен общий объект (динамическая библиотека)
1 голос
/ 08 ноября 2019

Как указано в engf-010, если символ, определенный в вашей статической библиотеке, не используется, компоновщик не поместит его в окончательный двоичный файл.

Одним из способов решения проблемы с использованием CMake будетиспользовать библиотеку OBJECT вместо библиотеки STATIC.

...