预处理器使函数名称不可访问

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,您需要显式键入 CreateFileACreateFileW,但这不是什么大问题。

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 指向正确的方法,它是。)