我目前正在使用互联网上很多地方提到的存储过程创建一个 DLL 和与之配套的客户端。基本上,创建一个在 Project.h 文件中实际定义 PROJECT_EXPORTS 的 DLL 项目。
像这样的东西:
// Assume the name of the project is SanProj and the header file is SanProj.h
#ifdef SANPROJ_EXPORTS
#define SANPROJ_API __declspec(dllexport)
#else
#define SANPROJ_API __declspec(dllimport)
#endif
现在使用此标头的常规方法是将其包含在 API 类的所有标头中,并在 DLL 中使用 SANPROJ_EXPORTS 进行“导出”声明,并在用作客户端时使用“导入”声明。例如,假设我们有一个带有货币类的头文件:
// currency.hpp
#include "SanProj.h"
#include <ostream>
#include <string>
namespace SanProj {
class SANPROJ_API Currency {
public:
Currency();
const std::string& name();
const std::string& code();
bool empty() const;
protected:
std::string name_;
std::string code_;
};
SANPROJ_API bool operator==(const Currency&,
const Currency&);
SANPROJ_API bool operator!=(const Currency&,
const Currency&);
SANPROJ_API std::ostream& operator<<(std::ostream& out, Currency& c);
}
另一个带有特定货币的头文件:
// allccy.hpp
namespace SanProj {
class SANPROJ_API USDCurrency : public Currency {
public:
USDCurrency() {
name_ = "American Dollar";
code_ = "USD";
}
};
class SANPROJ_API CADCurrency : public Currency {
public:
CADCurrency() {
name_ = "Canadian Dollar";
code_ = "CAD";
}
};
}
上述类构成了 DLL 项目的契约。现在让我们看一下客户端项目文件,它是一个具有功能的单个类main
:
#include "currency.hpp"
#include "allccy.hpp"
#include <iostream>
using namespace SanProj;
int main(int argc, char* argv[])
{
USDCurrency uccy;
std::cout << uccy;
}
假设所有引用/设置都已在 Visual Studio 项目中完成,我在尝试编译客户端时收到以下错误:
1>testdll.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall SanProj::USDCurrency::~USDCurrency(void)" (__imp_??1USDCurrency@SanProj@@QAE@XZ)
1>testdll.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall SanProj::USDCurrency::USDCurrency(void)" (__imp_??0USDCurrency@SanProj@@QAE@XZ)
dllimport
毫不奇怪,当我从文件中删除该部分SanProj.h
并创建可执行文件时,此错误就会消失。
我的问题是,dllimport
如果我们不能针对标头编译客户端,那么生成的 IDE 有什么意义?有没有办法我可以继续使用标头dllimport
并dllexports
删除链接器错误?另外,为什么要尝试解析dllimport
LIB 文件中的符号?
TIA
/佐助
编辑: VisualStudio 使用的链接器命令;如您所见,它具有 LIB 文件。
/OUT:"E:\vsprojects\SomeSln\Release\testdll.exe" /INCREMENTAL:NO /NOLOGO "E:\vsprojects\SomeSln\Release\SanProj.lib" "kernel32.lib" "user32.lib" "gdi32. lib”“winspool.lib”“comdlg32.lib”“advapi32.lib”“shell32.lib”“ole32.lib”“oleaut32.lib”“uuid.lib”“odbc32.lib”“odbccp32.lib”/MANIFEST/ ManifestFile:"Release\testdll.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"E:\vsprojects\SomeSln\Release\testdll.pdb" / SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /PGD:"E:\vsprojects\SomeSln\Release\testdll.pgd" /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE