Отделение библиотечных включений от программы с помощью библиотеки

Я создаю библиотеку DLL, которая будет экспортировать некоторые функции для использования в других проектах C++. В моей библиотеке я использую предварительно скомпилированные заголовки, а также Boost ASIO. Однако я хочу знать, возможно ли содержать все вещи, связанные с ASIO, в самой библиотеке, чтобы другой программе не нужно было их включать. Например:

stdafx.h (библиотека):

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <WinSock2.h>
#include <iostream>
#include <string.h>

#pragma comment(lib, "ws2_32")

#include <boost/asio.hpp>

Client.h (библиотека):

#pragma once

#ifdef LIB_EXPORTS
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif

using boost::asio::ip::tcp;

namespace TestLib {
    class Client {
        boost::asio::io_service io_service_;
        tcp::resolver resolver_;
        tcp::socket socket_;

    public:
        LIB_API Client();

        LIB_API bool Connect(const std::string& szHost, const std::string& szPort);

        virtual ~Client();
    };
}

Однако в моей программе, использующей эту библиотеку, я хочу иметь возможность включать Client.h без необходимости включать Boost ASIO. Поскольку я включаю этот заголовок без включения Boost ASIO, я получаю ошибки обо всех строках в Client.h, которые ссылаются на утилиты Boost, такие как оператор using и три закрытые переменные-члены.

Как мне создать библиотеку таким образом, чтобы моя другая программа должна была включать, например, только Client.h?


person John    schedule 17.11.2015    source источник
comment
Найдите pimpl на этом сайте. Это один из способов скрыть детали реализации, чтобы исключить зависимости включения.   -  person Anon Mail    schedule 17.11.2015
comment
@KryziK Извините, я невнимательно прочитал последнюю часть.   -  person Sreekar    schedule 17.11.2015


Ответы (1)


Я решил свою проблему, используя предложение Anon Mail. Вот решение:

Client.h (библиотека):

#pragma once

#ifdef LIB_EXPORTS
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif

namespace TestLib {
    class Client {
        struct Imp;
        std::unique_ptr<Imp> imp_;

    public:
        LIB_API Client();

        LIB_API bool Connect(const std::string& szHost, const std::string& szPort);

        LIB_API virtual ~Client();
    };
}

Client.cpp (библиотека):

namespace TestLib {
    struct Client::Imp {
        Client::Imp() : 
            io_service_(new boost::asio::io_service()), 
            resolver_(new tcp::resolver(*io_service_)),
            socket_(new tcp::socket(*io_service_)) {

        }

        std::shared_ptr<boost::asio::io_service> io_service_;
        std::shared_ptr<tcp::resolver> resolver_;
        std::shared_ptr<tcp::socket> socket_;
    };

    Client::Client() : imp_(new Imp) {
    }

    bool Client::Connect(const std::string& szHost, const std::string& szPort) {
        tcp::resolver::query query(szHost, szPort);

        tcp::resolver::iterator endpoint_iter = imp_->resolver_->resolve(query);

        boost::asio::connect(*imp_->socket_, endpoint_iter);

        return true;
    }
}

Простите меня, если я использую неправильные типы указателей. Любое руководство по этому решению будет высоко оценено!

person John    schedule 18.11.2015