预处理器使函数名称不可访问
Preprocessor makes function name unaccessabel
我必须使用 System.Data.SQLite 和 C++/CLI 创建一个 SQLite 数据库,但我 运行 遇到了问题。不幸的是,使用 C# 不是一个选项,如果是则没有问题。 (请不要建议我不要使用 C++/CLI,在这个项目中它不是一个选项。)
在 C# 中,以下代码可以正常工作。
using System.Data.SQLite;
void CreateDb(String file)
{
SQLiteConnection.CreateFile(file);
}
C++/CLI 中的等效代码并非没有问题。
using namespace System::Data::SQLite;
void CreateDb(System::String ^file)
{
SQLiteConnection::CreateFile(file); // error C2039
}
C2039 的确切错误文本是:
// 错误 C2039:'CreateFileA':不是 'System::Data::SQLite::SQLiteConnection'
的成员
如果我仔细查看 CreateFile 的定义,我会得到以下选择
#define CreateFile CreateFileW - c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\WinBase.h(9292)
#define CreateFile CreateFileA - c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\WinBase.h(9294)
这会导致 WinBase.h
中的以下几行
#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE
Microsoft SDK 混淆了我需要的确切名称,SQLite 没有为我提供 CreateFile[AW] 版本。
所以我在调用 SQLiteConnection.CreateFile(file) 的代码之前尝试了这个,我这样做是孤立的,这样其他代码就会受到它的影响。
#ifdef CreateFile
#undef CreateFile
#endif
它解决了我的问题(暂时),但是这有多安全?
有没有更好的方法解决这个问题?
非常感谢您的建议。
#undef
是我一直以来的处理方式。
how safe is this?
这是安全的。
如果您有其他名称冲突,您可能会再次遇到此问题。由于这样的名称冲突导致的编译错误很容易诊断,现在您知道您在寻找什么,因此如果需要,添加额外的 #undef
指令将很容易。
如果您需要调用 Win32 CreateFile
,您需要显式键入 CreateFileA
或 CreateFileW
,但这不是什么大问题。
Is there a better way of solving this problem?
是的,但这并不总是可能的。
更好的方法是不在使用 SQLite 的文件中 #include <Windows.h>
。这完全避免了这个问题。但是,并不总是可以像这样组织您的程序,因此 #undef
通常是解决方案。
(下一段不适用于您使用 SQLite 的场景:您使用的是托管版本,因此没有 headers。下一段适用于包含库 [=48= 的 C++ 库]. 为了完整起见,我将其包括在内,以防有人编写纯 C++。)
这里要注意的另一件事是 #include
-ing 库 headers 之前的 Windows headers。在这种情况下,class 定义本身 将 CreateFile
重命名为 CreateFileA
。如果你使用 #undef
,你会得到与你显示的相反的错误。您可以将 #define
留在原地,这有时会起作用,但这相当脆弱,所以我会避免这种情况。
(我在 C++ 应用程序中使用 MFC headers 运行 进行了一次:更改后的方法名称随处可见,甚至 Intellisense 也显示该名称以 "A" 结尾。它无论如何工作,因为 vTable 是在 MFC DLL 中初始化的,所以在调用应用程序中重要的是 vTable 指向正确的方法,它是。)
我必须使用 System.Data.SQLite 和 C++/CLI 创建一个 SQLite 数据库,但我 运行 遇到了问题。不幸的是,使用 C# 不是一个选项,如果是则没有问题。 (请不要建议我不要使用 C++/CLI,在这个项目中它不是一个选项。)
在 C# 中,以下代码可以正常工作。
using System.Data.SQLite;
void CreateDb(String file)
{
SQLiteConnection.CreateFile(file);
}
C++/CLI 中的等效代码并非没有问题。
using namespace System::Data::SQLite;
void CreateDb(System::String ^file)
{
SQLiteConnection::CreateFile(file); // error C2039
}
C2039 的确切错误文本是: // 错误 C2039:'CreateFileA':不是 'System::Data::SQLite::SQLiteConnection'
的成员如果我仔细查看 CreateFile 的定义,我会得到以下选择
#define CreateFile CreateFileW - c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\WinBase.h(9292)
#define CreateFile CreateFileA - c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\WinBase.h(9294)
这会导致 WinBase.h
中的以下几行#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE
Microsoft SDK 混淆了我需要的确切名称,SQLite 没有为我提供 CreateFile[AW] 版本。 所以我在调用 SQLiteConnection.CreateFile(file) 的代码之前尝试了这个,我这样做是孤立的,这样其他代码就会受到它的影响。
#ifdef CreateFile
#undef CreateFile
#endif
它解决了我的问题(暂时),但是这有多安全?
有没有更好的方法解决这个问题?
非常感谢您的建议。
#undef
是我一直以来的处理方式。
how safe is this?
这是安全的。
如果您有其他名称冲突,您可能会再次遇到此问题。由于这样的名称冲突导致的编译错误很容易诊断,现在您知道您在寻找什么,因此如果需要,添加额外的 #undef
指令将很容易。
如果您需要调用 Win32 CreateFile
,您需要显式键入 CreateFileA
或 CreateFileW
,但这不是什么大问题。
Is there a better way of solving this problem?
是的,但这并不总是可能的。
更好的方法是不在使用 SQLite 的文件中 #include <Windows.h>
。这完全避免了这个问题。但是,并不总是可以像这样组织您的程序,因此 #undef
通常是解决方案。
(下一段不适用于您使用 SQLite 的场景:您使用的是托管版本,因此没有 headers。下一段适用于包含库 [=48= 的 C++ 库]. 为了完整起见,我将其包括在内,以防有人编写纯 C++。)
这里要注意的另一件事是 #include
-ing 库 headers 之前的 Windows headers。在这种情况下,class 定义本身 将 CreateFile
重命名为 CreateFileA
。如果你使用 #undef
,你会得到与你显示的相反的错误。您可以将 #define
留在原地,这有时会起作用,但这相当脆弱,所以我会避免这种情况。
(我在 C++ 应用程序中使用 MFC headers 运行 进行了一次:更改后的方法名称随处可见,甚至 Intellisense 也显示该名称以 "A" 结尾。它无论如何工作,因为 vTable 是在 MFC DLL 中初始化的,所以在调用应用程序中重要的是 vTable 指向正确的方法,它是。)