我使用,在其头部定义内联函数的共享库。
下面是一个简化的测试情况下,由编译单元连接到库所看到(对于由库看到的版本,只需更换dllimport
由dllexport
)。
class __declspec(dllimport) MyClass {
public:
int myFunc2();
int myFunc1();
};
inline int MyClass::myFunc2(void) {
return myFunc1();
}
inline int MyClass::myFunc1(void) {
return 0;
}
编译这给了警告:
警告:“诠释MyClass的:: myFunc1()”没有DllImport属性与DLL链接被引用后重新声明[默认启用]
请注意,该功能定义的顺序是非常重要的,因为推杆的定义myFunc1
的定义之前myFunc2
在没有任何警告的结果。
注意,这个代码在编译时没有在Visual C ++警告。 这些警告是特定至少MinGW的,也许在一般的GCC。 编辑:它来到我的脑海里,我可能要验证是否警告不是由项目设置的标志之一抑制。
我的问题是,那么:
- 为什么这种行为?
- 声明
myFunc1
作为inline
类声明中解决了这个问题。 这是为什么 ? 这也是对推荐的方式做事。 - 难道还有其他(更好?)的方式来解决这个问题?
这个问题是有关的,因为在dllimport的作品通常意味着你只需要在第一个声明的方式一些魔术。
基本上,当你声明一个函数为dllimport再后来用除dllimport的相同的声明重新声明功能,第二个声明隐含得到dllimport的。 如果重新声明是不相同的,它不会隐dllimport的。
所以会发生什么这里是你首先声明函数为dllimport /非内联,然后宣布它作为非dllimport的/直列。 添加一个内联到所述第一声明可以解决问题,作为第二然后变得隐含dllimport的。 可替换地,增加一个__declspec(dllimport)
到所述第二声明应该解决这个问题。
需要注意的是重新排序的定义摆脱了警告,因为警告是关于重新声明之前使用它。 随着重排,你已不再是重复声明之前使用它,所以你得到任何警告,但它会使用非dllimport的版本(即,它不会使用的功能从DLL版本)。
还要注意,使用内联dllimport的是危险的。 对建成的dll的任何程序可以使用内联函数在其他一些地方和非内联函数(从DLL)。 即使这两个功能是相同的现在,DLL的未来版本可能会发生变化,并有不同的实现。 在这一点旧的程序可能会开始如果与该DLL的新版本上运行失常。
更多信息,多德的回答是:
我用测试MSVC 2017和MinGW-W64 7.2.0; 在这两种情况下,启用了优化,通话myFunc1()
从myFunc2
解析为内嵌版本,尽管警告。 即使身体myFunc1
被移动到下面main()
所以,我的初步结论是,它是安全的忽略此警告。
在全新的编译的利益,这似乎是在MinGW的-W64工作的唯一方法是将类标记定义中的函数声明inline
。 所述编译器不允许施加__declspec(dllimport)
以外的类中的函数定义。
我一直无法确定是否存在对G ++这将明确禁用该警告的警告标志。