Cri*_*ati 5 c++ windows dllimport visual-studio visual-c++
这基本上与[SO]: C2491: 'std::numpunct<_Elem>::id' : Define of dllimport static data member not allowed [close] 相同,但考虑以下事实:
请不要将其关闭或将其标记为重复项(至少,在没有仔细阅读和理解的情况下)。
主要.cpp:
#include <sstream>
//#define THROW_C2491
#if defined(THROW_C2491)
typedef int CharType;
#else
typedef char CharType;
#endif
int main() {
std::basic_stringstream<CharType> stream;
CharType c = 0x41;
stream << c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码稍作修改(简化),如果 THROW_C2491定义则无法编译:
Run Code Online (Sandbox Code Playgroud)xlocnum(294): error C2491: 'std::numpunct<_Elem>::id': definition of dllimport static data member not allowed
输出:
Run Code Online (Sandbox Code Playgroud)xlocnum(294): error C2491: 'std::numpunct<_Elem>::id': definition of dllimport static data member not allowed
注意事项:
[MS.Docs]:编译器错误 C2491非常简单,我很熟悉它,有一些答案(例如[SO]:在不同 VS2010 项目中从 C++ 代码调用 C 函数时出现链接器错误(@CristiFati 的答案),[ SO]:Excel VBA,无法从 DLL 文件中找到 DLL 入口点(@CristiFati 的回答))来支持我。
考虑到上面的注释,我知道这与Win处理char的方式(限制?)有关,但我没有看到代码和 error 之间有任何(直接)联系。[MS.Docs]上没有任何关于此行为的信息: basic_stringstream 类。我(浅薄地)浏览了所涉及的标准包含头文件,但到目前为止我还没有深入了解它。我是否错过了非常明显的事情?
其他参考文献(相同或类似的错误,但没有包含有效的修复):
值得一提的是,最终目标是构建一些第三方软件来实例化一些基于32 位 字符的流。
开始笔记:
方法:
快速(浅层)调查
在VStudio IDE上,双击“输出”窗口中的第二个注释(尝试编译文件后),然后在相关宏上重复单击RClick,然后从上下文菜单中选择“转到定义” ( F12 ):
xlocnum (#120) : (注释是原始文件/行的一部分)
__PURE_APPDOMAIN_GLOBAL _CRTIMP2_PURE static locale::id id; // unique facet id
Run Code Online (Sandbox Code Playgroud)yvals.h:(#494):
#define _CRTIMP2_PURE _CRTIMP2
Run Code Online (Sandbox Code Playgroud)crtdefs.h(#29+):
#ifndef _CRTIMP2
#if defined CRTDLL2 && defined _CRTBLD
#define _CRTIMP2 __declspec(dllexport)
#else
#if defined _DLL && !defined _STATIC_CPPLIB
#define _CRTIMP2 __declspec(dllimport) // @TODO - cfati: line #34: Here is the definition
#else
#define _CRTIMP2
#endif
#endif
#endif
Run Code Online (Sandbox Code Playgroud)正如所见,__declspec(dllimport)是在第 #34 行定义的。在宏上重复该过程_DLL,没有产生任何结果。在 [MSDN] 上找到:预定义宏:
我想到了两种可能的方法(都导致了成功的构建):
#undef _DLL(在main.cpp中,任何之前#include)。这是一个蹩脚的解决方法(gainarie)。它构建得很好,但是篡改这些东西可能(并且很可能会)在运行时触发未定义的行为这两个选项都不是完全令人满意,因此:
更深入一点
试图进一步简化事情(main.cpp):
#include <sstream>
//typedef unsigned short CharType; // wchar_t unsigned short
#define CharType unsigned short
int main() {
std::basic_stringstream<CharType> stream;
CharType c = 0x41;
stream << c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
注意事项:
typedef为#define(消除新类型定义的复杂性)unsigned shortwhich iswchar_t的定义 ( /Zc:wchar_t-) 以避免任何可能的类型大小/对齐差异
使用[MSDN]: /E(预处理到标准输出)和[MSDN]: /EP(不使用 #line 指令预处理到标准输出)“编译”上述代码(以便警告/错误仅引用当前文件中的行号):
#define( wchar_t vs. ) unsigned shortwchar_t编译时失败unsigned short并出现相同的错误#pragma message语句(是的,它们由预处理器处理,但仍然如此)(在每个警告/注释之前),注意到 2 之间存在一些差异#define,但到目前为止无法弄清楚为什么1template<> struct char_traits<char32_t>定义,所以我尝试了一下,它起作用了(至少编译了当前的程序)1(并且,正如预期的那样,sizeof(char32_t)是 4)。然后,找到了[MSDN]:char、wchar_t、char16_t、char32_t
注意事项:
wchar_t或signed char的char32_t内容unsigned short),所以我(还)不知道为什么它适用于某些类型但不适用于其他类型。这是一个开放的话题,每当我收到新的更新时,我都会分享它们底线:
根据经验发现,在使用基于字符的STL 容器时,允许使用以下类型:
charunsigned charsigned charwchar_tchar16_tchar32_tunsigned short(/Zc:wchar_t- 仅有的)最后注意事项:
@编辑0:
基于@IgorTandetnik在[MSDN]上的回答:Compile error for STL (stream)containers in Visual Studio,尽管仍然有一点迷雾:
unsigned char和signed char
我将接受这个作为答案。