包括DShow.h打破了BDS2006上的VCL AnsiString::sprintf()
Including DShow.h breaks VCL AnsiString::sprintf() on BDS2006
我终于有时间升级我的视频捕捉类。我想比较VFW(我一直使用到现在)和DirectShow。正如预期的那样,DirectShow更快,但是当我添加信息文本时,突然AnsiString::sprint()
不再是AnsiString
的成员。
经过一番斗争,我找到了一个变通办法,因为AnsiString::printf()
仍然有效,但我很好奇如何解决这个问题。也许dshow.h
和dstring.h
的一些定义是冲突的?
我删除了所有不必要的代码来显示这个问题:
//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#include <dshow.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
static int i=0;
Caption=AnsiString().sprintf("%i",i); // this does not work
AnsiString s; s.printf("%i",i); Caption=s; // this does work
i++;
}
//---------------------------------------------------------------------------
它只是一个简单的VCL表单应用程序与一个单一的TTimer
在它。TTimer
将计数器i
加1,并将其输出到表单的Caption
中。DirectX库甚至没有链接,只是包含头文件!
链接器输出错误:
[C++ Error] Unit1.cpp(20): E2316 'sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA' is not a member of 'AnsiString'
如果我交换vcl.h
和dshow.h includes, the compiler stops in
dstring.h '在这行:
AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this
错误信息:
[C++ Error] dstring.h(59): E2040 Declaration terminated incorrectly
因此,显然存在一些冲突(AnsiString
关键字是问题)。将dshow.h
放入namespace
中也没有帮助。
谁有什么线索?
Q1。如何解决这个问题?
Q2。到底是什么/在哪里造成的?
我能想到的唯一解决方案,应该工作(但我想避免它,如果我可以),是创建一个OBJ(或DLL)与DirectShow的东西,然后链接到一个标准的VCL项目不包括dshow.h
在它,当然出口必须没有任何有趣的东西,也是。
问题不在于dshow.h
本身,而实际上是strsafe.h
, dshow.h
默认包含。
strsafe.h
包含以下代码1:
#ifndef STRSAFE_NO_DEPRECATE
// Deprecate all of the unsafe functions to generate compiletime errors. If you do not want
// this then you can #define STRSAFE_NO_DEPRECATE before including this file
#ifdef DEPRECATE_SUPPORTED
...
#pragma deprecated(sprintf)
...
#else // DEPRECATE_SUPPORTED
...
#undef sprintf
#define sprintf sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;
...
#endif // DEPRECATE_SUPPORTED
#endif // !STRSAFE_NO_DEPRECATE
1对于许多其他已弃用的"不安全"C函数,有类似的#pragma
和#define
语句。
如果STRSAFE_NO_DEPRECATE
和DEPRECATE_SUPPORTED
都没有定义(在这种情况下),使用#define sprintf
会导致所有后续对任何类型的 sprintf
符号的引用在编译过程中被视为sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;
。
这就是为什么你得到编译器错误。当vcl.h
在strsafe.h
之前包含时,dstring.h
首先被包含,因此编译器看到AnsiString::sprintf()
方法的正确的声明,然后在编译器看到Timer1Timer()
代码之前包含strsafe.h
(可能是Unit1.h
),因此您对AnsiString().sprint("%i",i)
的调用实际上试图调用AnsiString().sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;("%i",i)
,失败。
当您交换vcl.h
和dshow.h
包含时,strsafe.h
中的#define sprintf
语句在dstring.h
包含之前被处理,因此编译器看到dstring.h
中AnsiString::sprintf()
方法的以下声明并失败:
AnsiString& __cdecl sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;(const char* format, ...); // Returns *this
为了防止这种行为,你可以在#include <dshow.h>
之后使用#undef sprintf
语句,就像JeffRSon建议的。然而,正确的解决方案是在#include <strsafe.h>
之前定义STRSAFE_NO_DEPRECATE
。你可以这样做:
在
#include <dshow.h>
语句之前添加#define STRSAFE_NO_DEPRECATE
将
STRSAFE_NO_DEPRECATE
添加到项目选项的条件列表中
此解决方案在MSDN上描述:
关于Strsafe.h
当你在文件中包含Strsafe.h时,被Strsafe.h函数取代的旧函数将被弃用。尝试使用这些较旧的函数将导致编译器错误,告诉您使用较新的函数。如果您想覆盖此行为,请在包含Strsafe.h之前包含以下语句。
#define STRSAFE_NO_DEPRECATE
要只允许字符计数函数,在包含Strsafe.h之前包含以下语句。
#define STRSAFE_NO_CB_FUNCTIONS
要只允许字节计数函数,在包含Strsafe.h之前包含以下语句。
#define STRSAFE_NO_CCH_FUNCTIONS
另一个支持的解决方案是在#include <dshow.h>
之前定义NO_DSHOW_STRSAFE
,这样它将不再包含strsafe.h
,感谢dshow.h
中的这段代码:
#ifndef NO_DSHOW_STRSAFE
#define NO_SHLWAPI_STRFCNS
#include <strsafe.h>
#endif
我没有dshow.h和string.h的这个版本,所以我不能自己检查,但从你引用的错误消息中,似乎在dshow.h或其依赖项的某个地方声明了一个"sprintf"宏。如果你能找到它,你可以看看。
为了防止这种行为,你需要删除这个宏。使用
#undef sprintf
- 如何在组合框中列出所有可用的 VCL 样式,并在组合框更改事件中应用该样式C++生成器?
- 将 Vcl::Controls::TCaption aka (System::UnicodeString) 转换为 co
- VCL 应用程序何时获取其应用程序>主窗体>句柄?
- 如何自定义排序 VCL 列表框?
- Truncate an AnsiString
- 将事件分配给在运行时动态创建的 VCL 控件
- 使用 VCL 的 C++:关闭辅助表单不会结束进程
- C 生成器 (C++) AnsiString Length 方法
- 重命名生成器 XE2 中的 VCL 表单类C++
- C++VCL询问.xlsb Excel数据库
- 如何从VCL项目的消息循环中调用其他功能
- VCL C (绘制时刷边框)
- AnsiString作为Embarcadero C++Builder中字符串类型的默认值
- VCL形式的多行控制
- 如何在VCL表单应用程序中创建和调用函数
- VCL表格申请
- 使用SetWindowsHookEx的C++只能在BCB2009中添加奇怪的vcl代码
- 跟踪 VCL 应用程序中表单的焦点增益和丢失
- AnsiString in C++?
- 包括DShow.h打破了BDS2006上的VCL AnsiString::sprintf()