__declspec是Microsoft VC中专用的关键字,它配合着一些属性可以对标准C/C++进行扩充。__declspec关键字应该出现在声明的前面。
__declspec(dllexport)用于Windows中的动态库中,声明导出函数、类、对象等供外面调用,省略给出.def文件。即将函数、类等声明为导出函数,供其它程序调用,作为动态库的对外接口函数、类等。
.def文件(模块定义文件)是包含一个或多个描述各种DLL属性的Module语句的文本文件。.def文件或__declspec(dllexport)都是将公共符号导入到应用程序或从DLL导出函数。如果不提供__declspec(dllexport)导出DLL函数,则DLL需要提供.def文件。
__declspec(dllimport)用于Windows中,从别的动态库中声明导入函数、类、对象等供本动态库或exe文件使用。当你需要使用DLL中的函数时,往往不需要显示地导入函数,编译器可自动完成。不使用__declspec(dllimport)也能正确编译代码,但使用__declspec(dllimport)使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于DLL中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL边界的函数调用中。声明一个导入函数,是说这个函数是从别的DLL导入。一般用于使用某个DLL的exe中。
In Microsoft,the extended attribute syntax for specifying storage-class information uses the__declspec keyword, which specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute.
Extended attribute grammar supports these Microsoft-specific storage-class attributes:align, allocate, appdomain, code_seg, deprecated, dllexport, dllimport, jitintrinsic, naked, noalias, noinline, noreturn, nothrow, novtable, process,restrict, safebuffers, selectany, and thread. It also supports these COM-object attributes: property and uuid. The code_seg, dllexport, dllimport, naked,noalias, nothrow, property, restrict, selectany, thread, and uuid storage-class attributes are properties only of the declaration of the object or function to which they are applied. The thread attribute affects data and objects only. The naked attribute affects functions only. The dllimport and dllexport attributes affect functions, data, and objects. The property, selectany, and uuid attributes affect COM objects.
The __declspec keywords should be placed at the beginning of a simple declaration. The compiler ignores, without warning, any __declspec keywords placed after * or& and in front of the variable identifier in a declaration. A __declspec attribute specified in the beginning of a user-defined type declaration applies to the variable of that type.
The dllexport and dllimport storage-class attributes are Microsoft-specific extensions to the C and C++ languages. You can use them to export and import functions, data, and objects to or from a DLL. These attributes explicitly define the DLL's interface to its client, which can be the executable file or another DLL. Declaring functions as dllexport eliminates the need for a module-definition(.def) file, at least with respect to the specification of exported functions.The dllexport attribute replaces the __export keyword. If a class is marked declspec(dllexport), any specializations of class templates in the class hierarchy are implicitly marked as declspec(dllexport). This means that class templates are explicitly instantiated and the class's members must be defined.
dllexport of a function exposes the function with its decorated name. For C++ functions,this includes name mangling. For C functions or functions that are declared as extern "C", this includes platform-specific decoration that's based on the calling convention. To export an undecorated name, you can link by using a Module Definition (.def) file that defines the undecorated name in an EXPORTS section.
以下是测试代码:新建一个动态库工程Library,然后在CppBaseTest工程中调用Library的接口:
library.hpp:
#ifndef FBC_LIBRARY_LIBRARY_HPP_
#define FBC_LIBRARY_LIBRARY_HPP_
// reference: http://geoffair.net/ms/declspec.htm
#ifdef _MSC_VER
#ifdef FBC_STATIC
#define FBC_API
#elif defined FBC_EXPORT
#define FBC_API __declspec(dllexport)
#else
#define FBC_API __declspec(dllimport)
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
FBC_API int library_add(int a, int b);
FBC_API int value;
#ifdef __cplusplus
}
#endif
template
class FBC_API Simple {
public:
Simple() = default;
void Init(T a, T b);
T Add() const;
private:
T a, b;
};
#endif // FBC_LIBRARY_LIBRARY_HPP_
library.cpp:
#include "library.hpp"
#include
#include
FBC_API int library_add(int a, int b)
{
value = 11;
fprintf(stdout, "File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
return (a+b);
}
template
void Simple::Init(T a, T b)
{
this->a = a;
this->b = b;
}
template
T Simple::Add() const
{
fprintf(stdout, "File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
return (a + b);
}
template class Simple;
template class Simple;
test_library.hpp:
#ifndef FBC_CPPBASE_TEST_TEST_LIBRARY_HPP_
#define FBC_CPPBASE_TEST_TEST_LIBRARY_HPP_
#include
namespace test_library_ {
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int library_add(int, int);
__declspec(dllimport) int value;
#ifdef __cplusplus
}
#endif
int test_library_1();
int test_library_2();
} // namespace test_library_
#endif // FBC_CPPBASE_TEST_TEST_LIBRARY_HPP_
test_library.cpp:
#include "test_library.hpp"
#include
#include
#include
namespace test_library_ {
int test_library_1()
{
int a{ 4 }, b{ 5 }, c{ 0 };
c = library_add(a, b);
fprintf(stdout, "%d + %d = %d\n", a, b, c);
fprintf(stdout, "value: %d\n", value);
return 0;
}
int test_library_2()
{
Simple simple1;
int a{ 4 }, b{ 5 }, c{ 0 };
simple1.Init(a, b);
c = simple1.Add();
fprintf(stdout, "%d + %d = %d\n", a, b, c);
Simple simple2;
std::string str1{ "csdn blog: " }, str2{ "http://blog.csdn.net/fengbingchun" }, str3;
simple2.Init(str1, str2);
str3 = simple2.Add();
fprintf(stdout, "contents: %s\n", str3.c_str());
return 0;
}
} // namespace test_library_
GitHub: https://github.com/fengbingchun/Messy_Test