我的解决方案(所有C ++)中有以下设置:
现在我想将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中创建一个定义FOO_EXPORTS的.cpp文件,然后包含包含我想要导出的方法的文件的标题。所以:
// 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。具有无法链接的方法的示例类。
答案 0 :(得分:3)
这当然无法工作,.lib代码编译错误的#define生效。因此它的功能不会被导出。
您必须使用定义的FOO_EXPORTS重建.lib或列出必须导出的函数的write a .def file。重建当然是迄今为止最不痛苦的解决方案,您可以简单地将另一个配置添加到lib项目并将项目包含在DLL解决方案中。或者始终使用定义的FOO_EXPORTS构建lib,它仍然是一个可以链接到非DLL项目的静态库。
答案 1 :(得分:0)
project1的所有已编译二进制代码都包含在.lib文件中。 如果不在编译时包含它,则不能在其他项目中使用它。
您可以将您希望在运行时共享的project1部分重新定义为共享库(即DLL)。