我的解决方案(所有C ++)中都有以下设置:
Project1,编译为静态库(.lib)。
编译为DLL的Project2包含在1.中生成的.lib。
Project3,包括在2中生成的DLL。
现在,我想将project1的功能公开给project3,而不直接包含项目1的.lib。我一直遇到链接器错误。
error LNK2001: unresolved external symbol
将项目1设置为以以下方式使用dllexport和dllimport(当然,FOO_API也位于要公开的类/方法的前面):
#if defined(FOO_STATIC)
#define FOO_API
#define FOO_TEMPLATE(type) template class type
#else
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#define FOO_TEMPLATE(type) template class FOO_API type
#else
#define FOO_API __declspec(dllimport)
#define FOO_TEMPLATE(type) extern template class FOO_API type
#endif
#endif
由于我们将Project1编译为静态库,因此不会采用dllexport路径(我们定义为FOO_STATIC)。但是,通过Project2的DLL,我想公开Project1的方法。我试图在Project2中创建一个.cpp文件,该文件定义了FOO_EXPORTS,然后包括了包含我要导出的方法的文件的标题。所以:
// somefile_that_will_be_built.cpp
#define FOO_EXPORTS
#include "a.h"
#include "b.h"
#include "c.h"
我希望这将触发Project1中的dllexport代码,以便将其包含在Project2的DLL中。我希望当Project3包含Project1标头时,它会走dllimport路径,并且比链接程序能找到所需的方法。所以:
#include "a.h"
class WrapThis:
public:
SomeMethodInA();
Project3可以编译,但是在链接期间找不到SomeMethodA()。我的方法行不通吗?我是否需要在Project2中编写模块定义文件?我希望能避免这种情况,因为我们在名称上存在一些歧义,并且名称修饰也无济于事(我知道可以将其关闭,但出于其他原因,我也不想这样做)。
任何帮助将不胜感激,因为我在这部分开发中的经验有限。
更新
其余错误(以4为例):
2>Stdafx.obj : error LNK2028: unresolved token (0A000683) "public: void __cdecl fooEx::Load(char const * const)" (? Load@fooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQEAAXQEBD@Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::Load(class System::String ^)" (?Load@FooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQE$AAMXPE$AAVString@System@@@Z)
2>Stdafx.obj : error LNK2028: unresolved token (0A000684) "public: void __cdecl fooEx::LoadHeader(char const * const)" (?LoadHeader@fooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQEAAXQEBD@Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::LoadHeader(class System::String ^)" (?LoadHeader@FooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQE$AAMXPE$AAVString@System@@@Z)
2>Stdafx.obj : error LNK2028: unresolved token (0A000686) "public: void __cdecl fooEx::Save(char const * const,double,double)" (?Save@fooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQEAAXQEBDNN@Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::Save(class System::String ^,double,double)" (?Save@FooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQE$AAMXPE$AAVString@System@@NN@Z)
2>Stdafx.obj : error LNK2028: unresolved token (0A000687) "public: void __cdecl fooEx::Save(char const * const)" (?Save@fooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQEAAXQEBD@Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::Save(class System::String ^)" (?Save@FooEx@Namespace4@Namespace1@Namespace2@Namespace3@@$$FQE$AAMXPE$AAVString@System@@@Z)
将Project1-classA(与FOO_EXPORT编译)到静态库中。
class FOO_API fooEx : public foo
{
public:
fooEx();
virtual void Free();
void Load(const char filename[]);
void LoadHeader(const char filename[]);
virtual void LoadRawData();
void Save(const char filename[]);
}
可能很重要:
Project1使用预编译的头。
Load和LoadHeader以完全相同的方式在多个文件中定义(foo类的其他扩展)。
虚拟方法在基类以及该基类的其他实现中定义。
Project2-编译为DLL。通过链接器输入包括Project1.lib,其他依赖项。
Project3-编译为DLL。示例类具有无法链接的方法。
最佳答案
当然,这是行不通的,.lib代码实际上是用错误的#define编译的。因此,其功能将不会导出。
您必须使用定义为FOO_EXPORTS的.lib重建,或者使用write a .def file列出必须导出的函数。到目前为止,重建当然是最痛苦的解决方案,您可以简单地向lib项目添加另一个配置,然后将该项目包括在DLL解决方案中。或始终使用定义的FOO_EXPORTS来构建库,它仍然是可以链接到非DLL项目中的静态库。