刚开始为一个非常简单的自动化测试框架进行编码以供内部使用。 (我知道那里有成百上千的人 - 真的也很好,但此刻并不感兴趣,所以请不要指出我的任何一个,请;))然后我遇到了以下问题我无法解释,因此请求您的帮助。
我将以下代码作为DLL的一部分:
(代码几乎不是一个胚胎,花了我2分钟的时间来编写,所以它的逻辑,结构 - 没有 - 在任何方面都得到了改进。)
h文件:
#pragma once
#ifdef __DLL__ // Defined in DLL-project
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT
#endif
class DLLEXPORT AutoTest
{
public:
enum eTestID {TESTID_SomeFunction};
AutoTest(eTestID id, LPVOID lpData)
{
if(sm_bTestsActive)
ExecTest(id, lpData);
}
void ActivateTests();
private:
static void ExecTest(eTestID id, LPVOID lpData)
{
}
static BOOL sm_bTestsActive;
};
CPP-文件:
#include "StdAfx.h"
#include "AutoTest.hpp"
BOOL AutoTest::sm_bTestsActive = FALSE;
void AutoTest::ActivateTests()
{
sm_bTestsActive=TRUE;
}
编译得很好,DLL就会生成。
这是我的问题 - 当用以下代码实例化类时
AutoTest(AutoTest::TESTID_SomeFunction, &SomeData);
来自主应用程序,链接器失败并带有
error LNK2001: unresolved external symbol "private: static int AutoTest::sm_bTestsActive" (?sm_bTestsActive@AutoTest@@0HA)
< 2分钟写 - 现在进行5个小时,以了解它失败的原因! :0 的
这里有什么有趣的 - 如果我将构造函数移动到cpp文件(没有内联)它就可以正常工作了!?!?
以下代码:
h文件:
#pragma once
#ifdef __DLL__ // Defined in DLL-project
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT
#endif
class DLLEXPORT AutoTest
{
public:
enum eTestID {FK3059};
AutoTest(eTestID id, LPVOID lpData);
void ActivateTests();
private:
static void ExecTest(eTestID id, LPVOID lpData)
{
}
static BOOL sm_bTestsActive;
};
CPP-文件:
#include "StdAfx.h"
#include "AutoTest.hpp"
BOOL AutoTest::sm_bTestsActive = FALSE;
AutoTest::AutoTest(eTestID id, LPVOID lpData)
{
if(sm_bTestsActive)
ExecTest(id, lpData);
}
void AutoTest::ActivateTests()
{
sm_bTestsActive=TRUE;
}
(我在粘贴后对代码进行了一些小修改,因此可能会有或可能没有简单的语法错误。)
此外,如果我从内联版本构造函数中删除对静态成员的引用,它可以正常工作。
关于内联版本为什么不起作用的任何想法?
答案 0 :(得分:2)
请注意您对DLLEXPORT
的定义。
确保在构建DLL时将其正确扩展为__declspec(dllexport)
,或在构建客户端时__declspec(dllimport)
。
我建议使用一个名称比通用DLLEXPORT
更具体的宏(以避免与其他具有相同名称的宏冲突)。
从内联成员函数访问静态数据成员对我来说很好(使用VS2013测试)。
最小的重复:
使用空DLL项目和空控制台应用程序项目创建Visual Studio解决方案。
在DLL项目中添加两个文件:
<强> DllClass.h 强>:
#pragma once
#ifndef TEST_DLL_CLASS
#define TEST_DLL_CLASS __declspec(dllimport)
#endif
class TEST_DLL_CLASS DllClass
{
public:
DllClass();
int GetMember() const
{
return m_data1;
}
static int GetStaticMember()
{
return sm_data2;
}
private:
int m_data1;
static int sm_data2;
};
<强> DllClass.cpp 强>:
#define TEST_DLL_CLASS __declspec(dllexport)
#include "DllClass.h"
int DllClass::sm_data2 = 2;
DllClass::DllClass()
: m_data1(1)
{
}
在控制台应用程序项目中,添加一个文件:
<强> Test.cpp的强>:
#include "..\DllTestClass\DllClass.h"
#include <iostream>
using namespace std;
#pragma comment(lib, "DllTestClass")
int main()
{
DllClass dllClass;
cout << dllClass.GetMember() << endl;
cout << DllClass::GetStaticMember() << endl;
}
确保在构建控制台测试应用程序时,链接器可以找到DLL .lib( DllTestClass.lib )文件。
为此,您可以导航控制台应用程序的项目属性,转到:
Project Properties | Linker | Additional Library Directories
并将$(OutDir)
添加到其他库目录中,使其成为:
$(OutDir);%(AdditionalLibraryDirectories)
为我构建并正常工作。
答案 1 :(得分:1)
应该是:
#ifdef __DLL__ // Defined in DLL-project
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT __declspec( dllimport )
#endif
您可以使用
dllimport
或dllexport
属性声明C ++类。这些形式意味着导入或导出整个类。以这种方式导出的类称为可导出类。
the documentation中的更多信息。