C++ 如何从 dll 导出静态 class 成员?
C++ How to export a static class member from a dll?
//API mathAPI.h, Dll.cpp 和 Test.cpp
#ifdef __APIBUILD
#define __API __declspec(dllexport)
//#error __APIBUILD cannot be defined.
#else
#define __API __declspec(dllimport)
#endif
class math
{
public:
static __API double Pi;
static __API double Sum(double x, double y);
};
// Dll.cpp __APIBUILD 定义
#include "mathAPI.h"
double math::Pi = 3.14;
double math::Sum(double x, double y)
{
return x + y;
}
// Test.cpp __APIBUILD 未定义
#include <iostream>
#pragma comment(lib, "dll.lib")
#include "mathAPI.h"
int main()
{
std::cout << math::Pi; //linker error
std::cout << math::Sum(5.5, 5.5); //works fine
return 0;
}
错误 1 error LNK2001: 无法解析的外部符号 "public: static double Math::Pi" (?Pi@Math@@2NA)
我如何让它工作?
而不是一一导出成员,export whole class。另外,我完全不知道这段代码是如何工作的——你没有提供 sum()
的定义(缺少 class 范围运算符),这就是链接器应该抱怨的(而不是 math::Sum()
, 你定义了新的全局 sum()
).
mathAPI.h
#ifdef __APIBUILD
#define __API __declspec(dllexport)
#else
#define __API __declspec(dllimport)
#endif
class __API math //Add __API to export whole class
{
public:
static double Pi;
static double Sum(double x, double y);
};
Dll.cpp
#include "mathAPI.h"
double math::Pi = 3.14;
double math::Sum(double x, double y) //You missed 'math::' here before
{
return x + y;
}
就是这样。
编辑
不过,您应该仍然会收到错误消息。那是因为你打错了,我没有注意到(而且你没有 post 真正的代码!)。在你的 Dll.cpp
中,你写道:
double math::Pi = 3.14;
虽然您 post 做了一些不同的事情,但我敢肯定,您的 class 被命名为 Math
,而不是 math
,因为链接器正在尝试搜索:
?Pi@Math@@2NA
所以它正在 class Math
中查找。这是最有可能的猜测。不过,我很确定,您没有 post 真实的 代码,而是手写的片段。
获取 Pi 值的更好解决方案是创建一个静态方法来初始化和 return 它,就像下面的 DLL.cpp:
#include "mathAPI.h"
// math::getPi() is declared static in header file
double math::getPi()
{
static double const Pi = 3.14;
return Pi;
}
// math::Sum() is declared static in header file
double math::Sum(double x, double y)
{
return x + y;
}
这会阻止你使用未初始化的值 Pi,并且会做你想做的事。
请注意,初始化所有静态 values/members 的最佳做法是在 function/method 调用中初始化它们。
//API mathAPI.h, Dll.cpp 和 Test.cpp
#ifdef __APIBUILD
#define __API __declspec(dllexport)
//#error __APIBUILD cannot be defined.
#else
#define __API __declspec(dllimport)
#endif
class math
{
public:
static __API double Pi;
static __API double Sum(double x, double y);
};
// Dll.cpp __APIBUILD 定义
#include "mathAPI.h"
double math::Pi = 3.14;
double math::Sum(double x, double y)
{
return x + y;
}
// Test.cpp __APIBUILD 未定义
#include <iostream>
#pragma comment(lib, "dll.lib")
#include "mathAPI.h"
int main()
{
std::cout << math::Pi; //linker error
std::cout << math::Sum(5.5, 5.5); //works fine
return 0;
}
错误 1 error LNK2001: 无法解析的外部符号 "public: static double Math::Pi" (?Pi@Math@@2NA)
我如何让它工作?
而不是一一导出成员,export whole class。另外,我完全不知道这段代码是如何工作的——你没有提供 sum()
的定义(缺少 class 范围运算符),这就是链接器应该抱怨的(而不是 math::Sum()
, 你定义了新的全局 sum()
).
mathAPI.h
#ifdef __APIBUILD
#define __API __declspec(dllexport)
#else
#define __API __declspec(dllimport)
#endif
class __API math //Add __API to export whole class
{
public:
static double Pi;
static double Sum(double x, double y);
};
Dll.cpp
#include "mathAPI.h"
double math::Pi = 3.14;
double math::Sum(double x, double y) //You missed 'math::' here before
{
return x + y;
}
就是这样。
编辑
不过,您应该仍然会收到错误消息。那是因为你打错了,我没有注意到(而且你没有 post 真正的代码!)。在你的 Dll.cpp
中,你写道:
double math::Pi = 3.14;
虽然您 post 做了一些不同的事情,但我敢肯定,您的 class 被命名为 Math
,而不是 math
,因为链接器正在尝试搜索:
?Pi@Math@@2NA
所以它正在 class Math
中查找。这是最有可能的猜测。不过,我很确定,您没有 post 真实的 代码,而是手写的片段。
获取 Pi 值的更好解决方案是创建一个静态方法来初始化和 return 它,就像下面的 DLL.cpp:
#include "mathAPI.h"
// math::getPi() is declared static in header file
double math::getPi()
{
static double const Pi = 3.14;
return Pi;
}
// math::Sum() is declared static in header file
double math::Sum(double x, double y)
{
return x + y;
}
这会阻止你使用未初始化的值 Pi,并且会做你想做的事。
请注意,初始化所有静态 values/members 的最佳做法是在 function/method 调用中初始化它们。