如何为现有代码库创建公共API?

时间:2010-12-15 20:10:26

标签: c++ api

我正在尝试为私有代码库创建一个公共C ++ API,它也是用C ++编写的。我试着这样做:

  • 为每个私有类创建一个包装器API类。
  • 有一个公共API基类,它有一个指向私有类的指针。
  • API类实现不包含任何功能,只是将方法调用转发给其私有对应项。

这似乎是一种合理的方法。然而,实际上它很快就会导致代码非常笨拙。这是一个代表我遇到的问题的例子。

(编辑:也可以查看代码here)。


私有API类(这里没问题)

namespace Core {


// Base class for all Core classes.
class CoreObject
{
public:
    virtual ~CoreObject();
};    

class Interface;
class Stream;    

class Server : public CoreObject
{
public:
    Interface * createInterface();

private:
    std::vector<Interface*> mInterfaces;

};    

class Interface : public CoreObject
{
public:
    void addStream(Stream * stream);

    const Stream * getStreamByIndex(std::size_t index) const;

    std::size_t streamCount() const;

private:
    std::vector<Stream*> mStreams;
};    

class Stream : public CoreObject
{
public:
    void start();

    void stop();

private:
    std::string mStats;
};


} // Core


公共API类声明(到目前为止一直很好)

namespace Core {
class CoreObject;
}


namespace API {


class APIStream;
class APIInterface;    

// Base class for all API classes.
class APIObject
{
public:
    APIObject(Core::CoreObject * inCoreObject);

    virtual ~APIObject();

    Core::CoreObject * getCoreObject();

    const Core::CoreObject * getCoreObject() const;

    void setCoreObject(Core::CoreObject * inCoreObject);

private:
    Core::CoreObject * mCoreObject; 
};    

class APIServer : public APIObject
{
public:
    APIServer();

    APIInterface * createInterface();
};    

class APIInterface : public APIObject
{
public:
    APIInterface();

    void addStream(APIStream * stream);

    const APIStream * getStreamByIndex(std::size_t index) const;

    APIStream * getStreamByIndex(std::size_t index);

    std::size_t streamCount() const;
};    

class APIStream : public APIObject
{
public:
    APIStream();

    void start();

    void stop();
};


API实现(太多演员阵容,通常很笨拙)

#include "API.h"
#include "Core.h"


namespace API {


APIObject::APIObject(Core::CoreObject * inCoreObject) :
    mCoreObject(inCoreObject)
{
}

APIObject::~APIObject()
{
}

Core::CoreObject * APIObject::getCoreObject()
{
    return mCoreObject;
}


const Core::CoreObject * APIObject::getCoreObject() const
{
    return mCoreObject;
}


void APIObject::setCoreObject(Core::CoreObject * inCoreObject)
{
    mCoreObject = inCoreObject;
}


//
// APIServer
//
APIServer::APIServer() :
    APIObject(new Core::Server)
{
}    

APIInterface * APIServer::createInterface()
{
    Core::Server * coreServer = static_cast<Core::Server*>(getCoreObject());
    Core::Interface * coreInterface = coreServer->createInterface();
    APIInterface * result(new API::APIInterface);
    result->setCoreObject(coreInterface);
    return result;
}


//
// APIInterface
//
APIInterface::APIInterface() :
    APIObject(new Core::Interface)
{
}    

void APIInterface::addStream(APIStream * apiStream)
{
    Core::Stream * coreStream = static_cast<Core::Stream *>(apiStream->getCoreObject());
    Core::Interface * coreInterface = static_cast<Core::Interface*>(getCoreObject());
    coreInterface->addStream(coreStream);
}


//
// APIStream
//
const APIStream * APIInterface::getStreamByIndex(std::size_t index) const
{
    const Core::Interface * coreInterface = static_cast<const Core::Interface*>(getCoreObject());
    const Core::Stream * coreStream = coreInterface->getStreamByIndex(index);

    // Now how I get the the APIStream object?
    return 0;
}

std::size_t APIInterface::streamCount() const
{
    const Core::Interface * coreInterface = static_cast<const Core::Interface*>(getCoreObject());
    return coreInterface->streamCount();
}    

APIStream::APIStream() :
    APIObject(new Core::Stream)
{
}    

void APIStream::start()
{
    static_cast<Core::Stream*>(getCoreObject())->start();
}       

void APIStream::stop()
{
    static_cast<Core::Stream*>(getCoreObject())->stop();
}    

} // API


正如您所看到的,实现看起来并不太好。感谢您对这些问题的回答或见解:

  • 我哪里出错了?
  • 我该怎么办呢?


更新

约翰·迪布林的建议似乎非常。正如您在improved code中所看到的,所有问题都得到了彻底解决。

我仍然需要在明天的工作中将此解决方案应用于实际代码。我很想知道它在那里有多好。

2 个答案:

答案 0 :(得分:4)

当做这种事情时,API和实现对象之间或多或少存在一对一的关系,我通常会使用静态factory method,并且实现类派生自API类。像这样:

file:api.h

class Interface
{
public:
  static Interface* Create();
  virtual void Foo() = 0;
};

file:impl.h

class Concrete : public Interface
{
public:
  void Foo() {};
};

file:impl.cpp

Interface* Interface::Create()
{
  return new Concrete;
}

这有很多好处。包括:

  1. Create可以构建许多不同的实现,而Interface的ABI不必更改。
  2. 返回类型依赖于语言的协方差规则,因此不需要强制转换。
  3. 调试更容易,因为您可以确切地知道您所拥有的Interface类型。

答案 1 :(得分:2)

请参阅Adapter模式