C++ 在MinGW中导入内联函数
我正在使用一个共享库,它在头文件中定义内联函数 这里是一个简化的测试用例,正如链接到库的编译单元所看到的(对于库看到的版本,只需将C++ 在MinGW中导入内联函数,c++,dll,linker,mingw,inline,C++,Dll,Linker,Mingw,Inline,我正在使用一个共享库,它在头文件中定义内联函数 这里是一个简化的测试用例,正如链接到库的编译单元所看到的(对于库看到的版本,只需将dllimport替换为dllexport) 编译此文件时会发出警告: 警告:在没有dllimport的情况下重新声明了“int MyClass::myFunc1()” 使用dll链接引用后的属性[默认启用] 请注意,函数的定义顺序很重要,因为将myFunc1的定义放在myFunc2的定义之前不会导致任何警告 注意,此代码在VisualC++中没有警告的情况下编译。这
dllimport
替换为dllexport
)
编译此文件时会发出警告:
警告:在没有dllimport的情况下重新声明了“int MyClass::myFunc1()”
使用dll链接引用后的属性[默认启用]
请注意,函数的定义顺序很重要,因为将myFunc1
的定义放在myFunc2
的定义之前不会导致任何警告
注意,此代码在VisualC++中没有警告的情况下编译。这些警告至少针对MinGW,可能针对GCC。编辑:我想到,我可能必须验证该警告是否未被项目设置的某个标志所禁止
我的问题是:- 为什么会有这种行为
- 在类声明中将
声明为myFunc1
,可以解决此问题。为什么呢?这也违反了做事的原则inline
- 是否有其他(更好的?)方法来解决此问题
- 问题的出现是因为dllimport的工作方式有一些魔力,这通常意味着您只需要在第一次声明时使用它
基本上,当您将函数声明为dllimport,然后使用除dllimport之外的相同声明重新声明该函数时,第二个声明隐式地获取dllimport。如果重新声明不相同,则不会获得隐式dllimport
这里发生的事情是,首先将函数声明为dllimport/non-inline,然后将其声明为non-dllimport/inline。在第一个声明中添加内联可以解决问题,因为第二个声明将隐式地成为dllimport。或者,在第二个声明中添加一个
\uu declspec(dllimport)
应该可以解决这个问题
请注意,对定义重新排序会消除警告,因为警告是关于在重新声明之前使用它。使用重新排序时,您在重新声明之前不再使用它,因此不会收到任何警告,尽管它将使用非dllimport版本(即,它永远不会使用dll中函数的版本)
另外请注意,使用内嵌dllimport是危险的。根据dll构建的任何程序可能在某些位置使用内联函数,而在其他位置使用非内联函数(来自dll)。即使这两个函数现在是相同的,dll的未来版本也可能会更改,并具有不同的实现。在这一点上,如果使用新版本的dll运行,旧程序可能会开始出现错误。有关Chris Dodd答案的更多信息: 我使用和MinGW-w64 7.2.0进行了测试;在这两种情况下,启用优化后,从
myFunc2
调用myFunc1()
将解析为内联版本,尽管出现警告。即使myFunc1
的主体被移动到main()
的下方
因此,我的初步结论是,忽略这一警告是安全的
为了实现干净的编译,在MinGW-w64中唯一有效的方法是将类定义中的函数声明标记为
inline
。编译器不允许将\uu declspec(dllimport)
应用于类外函数定义
我无法确定g++是否有一个警告标志专门禁用此警告。实际上,在第二个声明中添加一个
\u declspec(dllimport)
会得到一个警告:内联函数“int MyClass::myFunc1()”声明为dllimport:attribute ignored[-Wattributes]
(对于myFunc2
)也是一样。这也有点令人困惑,但我假设所有这些都是任意的。对于C来说显然不是这样。代码片段\u declspec(dllimport)void f(void);void f(void);
给出了警告:警告:“f”在没有dllimport属性的情况下重新声明:先前的dllimport被忽略了。为什么?
class __declspec(dllimport) MyClass {
public:
int myFunc2();
int myFunc1();
};
inline int MyClass::myFunc2(void) {
return myFunc1();
}
inline int MyClass::myFunc1(void) {
return 0;
}