一般规则和限制
Microsoft 专用
如果在不使用
dllimport
或dllexport
特性的情况下声明函数或对象,则该函数或对象不会被视为 DLL 接口的一部分。 因此,函数或对象的定义必须存在于该模块或同一程序的另一个模块中。 若要使函数或对象成为 DLL 接口的一部分,必须将其他模块中函数或对象的定义声明为dllexport
。 否则,将生成链接器错误。如果使用
dllexport
特性声明函数或对象,则其定义必须出现在同一程序的某个模块中。 否则,将生成链接器错误。如果程序中的单个模块包含对同一函数或对象的
dllimport
和dllexport
声明,则dllexport
特性优先于dllimport
特性。 但是,会生成编译器警告。 例如:__declspec( dllimport ) int i; __declspec( dllexport ) int i; // Warning; inconsistent; // dllexport takes precedence.
在 C++ 中,可初始化全局声明的局部数据指针或静态局部数据指针,或利用使用
dllimport
特性声明的数据对象的地址进行初始化,后一种初始化方法在 C 中会生成错误。此外,还可利用使用dllimport
特性声明的函数的地址初始化静态局部函数指针。 在 C 中,此类赋值会将指针设置为指向 DLL 导入形式转换 (thunk)(将控制权转交给函数的代码存根)的地址而不是函数的地址。 在 C++ 中,此类赋值会将指针设置为指向函数的地址。 例如:__declspec( dllimport ) void func1( void ); __declspec( dllimport ) int i; int *pi = &i; // Error in C static void ( *pf )( void ) = &func1; // Address of thunk in C, // function in C++ void func2() { static int *pi = &i; // Error in C static void ( *pf )( void ) = &func1; // Address of thunk in C, // function in C++ }
但是,由于包含对象声明中的
dllexport
特性的程序必须在程序中的某个位置为对象提供定义,因此可以利用dllexport
函数的地址初始化全局或局部静态函数指针。 同样,您可以利用dllexport
数据对象的地址初始化全局或局部静态数据指针。 例如,以下代码在 C 或 C++ 中不会生成错误:__declspec( dllexport ) void func1( void ); __declspec( dllexport ) int i; int *pi = &i; // Okay static void ( *pf )( void ) = &func1; // Okay void func2() { static int *pi = &i; // Okay static void ( *pf )( void ) = &func1; // Okay }
如果将
dllexport
应用于具有未标记为dllexport
的基类的常规类,编译器将生成 C4275。如果基类是类模板的专用化,则编译器将生成相同的警告。 若要解决此问题,请将基类标记为
dllexport
。 类模板专用化的问题在于在何处放置__declspec(dllexport)
;不允许标记类模板。 相反,应显式实例化类模板并将此显式实例化标记为dllexport
。 例如:template class __declspec(dllexport) B<int>; class __declspec(dllexport) D : public B<int> { // ...
如果模板自变量是派生类,则此解决方法将失败。 例如:
class __declspec(dllexport) D : public B<D> { // ...
由于这是模板的常见模式,因此当
dllexport
应用于具有一个或多个基类的类时,以及一个或多个基类是类模板的专用化时,编译器更改了该特性的语义。 在这种情况下,编译器会将dllexport
隐式应用于类模板的专用化。 可执行以下代码而不会收到警告:class __declspec(dllexport) D : public B<D> { // ...
结束 Microsoft 专用
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈