如何在C ++中设置多项目解决方案?

时间:2015-01-10 15:16:38

标签: c++ visual-studio dll linker

我是C ++的新手,我很难让我的dll引用工作。我已经尝试让它工作了几天,但我发现的一些解释通常都是指做x或y,但不要告诉我如何做x或y。由于我不是C ++老手,我需要有人来指导我。我想做的是以下几点:

MySolution
    MyExe (Win32 .exe)
        Main.h
        Main.cpp
            (constructs ImplementationB calls the methods as defined by InterfaceA, then deletes the instances)
            (calls/fills HelperC.Foobar)
    MyInterfaces (dll)
        InterfaceA.h
            ~InterfaceA();
            virtual void DoSomething();
    MyUtils (dll)
        HelperC.h
            static float Foobar;
        HelperD.cpp
            float HelperC::Foobar = 1.0f;
    MyImplementations (dll)
        ImplementationB : InterfaceA
            (uses the value from HelperC.Foobar)

MyExeMyImplementations项目包含大部分执行代码。但是,我需要一个接口,所以我需要一个接口项目(MyInterfaces)。我需要一些需要从MyExeMyImplementations访问的辅助类,因此MyUtils。我希望这个帮助程序类可以静态使用,但它不是强制性的。

在我开始使用MyUtils类添加HelperC之前,我有一个编译版本。我必须使用__declspec(dllexport)标记界面析构函数,以及DoSomething方法。我还必须标记ImplementationB的构造函数,以便从MyExe实例化它,这是有道理的。但是,当我尝试使用__declspec(dllexport)标记整个类(实现和接口)时,该示例将无法编译( 有意义)。

从我读过的内容来看,在dll中使用静态字段并使用外部代码中的静态字段并没有真正起作用。因此,作为替代方案,我使Foobar非静态并将HelperC实例传递给方法,如InterfaceA所述。由于我已经有了简单的课程,我认为这应该也可以。但是,现在编译器在ImplementationB(LNK2019)的构造函数上抛出错误。

简而言之:我在与我的更改无关的部分中发现链接错误,并且有一些小文档描述了我需要执行的具体步骤才能获得简单的dll参考工作。
有人可以指出我需要添加什么以及我需要添加它以使其编译?此外,有些人对C ++ dll引用不做什么并且没有帮助(例如,不要在项目中使用静态)。

1 个答案:

答案 0 :(得分:0)

经过多次挖掘,我发现罪魁祸首是一个神奇的项目设置。它名为Ignore Import Library,位于Project Properties->Linker->General,默认设置为Yes,大多数情况下应设置为No。该设置告诉可执行项目在编译期间使用dll的lib文件。这听起来仍然很奇怪(听起来像重复的构建输出),但据我所知,lib文件描述如何链接到dll。如果您的dll在构建期间生成了lib,则可能需要将设置设置为No

我还了解到,为了能够将HelperC类用作静态可访问的帮助程序,我需要将dllimportmacro trick结合使用,如@drescherjm所述。只需要dllimport声明就可以跨库使用数据成员(静态类字段或全局定义的变量)。它也可以应用于函数,虽然它不是必需的,在这种情况下,它在库链接期间提供了轻微的性能提升。

为了完整性,我的项目结构在开始工作之后:

MySolution
    MyExe (Win32 .exe, Debugger Type=Mixed)
        Main.h
        Main.cpp
            (constructs ImplementationB calls the methods as defined by InterfaceA, then deletes the instances)
            (calls/fills HelperC::Foobar)
    MyInterfaces (dll, Ignore Import Library=Yes, because there is no .lib after building)
        InterfaceA.h
            class __declspec(dllexport) InterfaceA
                ~InterfaceA() {};
                virtual void DoSomething() = 0;
    MyUtils (dll, Ignore Import Library=No)
        HelperC.h
            class __declspec(dllimport/dllexport) HelperC // (see macro trick)
                static float Foobar;
        HelperD.cpp
            float HelperC::Foobar = 1.0f;
    MyImplementations (dll, Ignore Import Library=No)
        ImplementationB.h
            class __declspec(dllexport) ImplementationB : public InterfaceA
                ImplementationB();
                ~ImplementationB();
                void DoSomething();
        ImplementationB.cpp
            ImplementationB::ImplementationB() {};
            ImplementationB::~ImplementationB() {};
            ImplementationB::DoSomething() { /* Omitted */ };
                (uses HelperC::Foobar in implementation)

旁注:如果在Visual Studio中添加了默认的C ++类库项目,则可能需要将Project Properties->Debugging->Debugger Type设置翻转为Mixed,然后才能设置/使用断点DLL代码。请参阅this

我希望这可以帮助那些在C ++(和Visual Studio)中与dll进行摔跤的人。