2016-10-12 72 views
1

我终于有一些时间来升级我的视频捕获类。我想比较VFW(我已经使用到现在)和DirectShow。正如预期的那样,DirectShow更快,但是当我添加信息文本时,突然AnsiString::sprint()不再是AnsiString的成员。包括DShow.h中断BDS2006上的VCL AnsiString :: sprintf()

经过一番斗争,我找到了一个解决方法,AnsiString::printf()仍然有效,但我很好奇如何解决这个问题。也许一些定义从dshow.hdstring.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窗体应用程序上有一个单一的TTimerTTimer正在递增计数器i并将其输出到表格的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关键字是t他问题)。将dshow.h置入namespace也无济于事。

有没有人有任何线索?

Q1。如何解决这个问题?第二季度销售价格下降,第二季度销售价格下降,第三季度销售价格下降。什么/究竟在哪里造成这种情况?

,我能想到的,并且应该工作(但我想,以避免它,如果我能)唯一的解决办法,是建立与的DirectShow东西的OBJ(或DLL),和然后将其链接到一个标准的VCL项目中,其中不包括dshow.h,当然,出口也必须没有任何有趣的东西。

+1

在包括dshow后尝试“#undef sprintf”。h – JeffRSon

+1

@JeffRSon是的,它的工作作出答案,所以我可以接受它是奇怪的,因为VCL包括在DShow之前......但它的工作原理 – Spektre

回答

1

问题不在于dshow.h本身,而是实际上与strsafe.h相反,其中dshow.h默认包含。

strsafe.h包含以下代码:

#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 

有许多其他弃用 “不安全” 的C函数类似#pragma#define语句。

如果两个STRSAFE_NO_DEPRECATEDEPRECATE_SUPPORTED没有定义(这是在这种情况下的情况下),使用的#define sprintf导致编译期间到被视为sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;任何种类sprintf符号的所有后续的引用。

这就是为什么你得到编译器错误。当vcl.hstrsafe.h之前包括,dstring.h被首次列入,所以编译器看到正确声明为AnsiString::sprintf()方法,然后strsafe.h被列入(可能由Unit1.h)编译器看到你的Timer1Timer()代码之前,所以你要AnsiString().sprint("%i",i)电话是实际上试图拨打AnsiString().sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;("%i",i),这失败了。

当你交换vcl.hdshow.h包括,在strsafe.h#define sprintf语句获取dstring.h之前处理被包括在内,所以编译器看到的AnsiString::sprintf()方法如下声明中dstring.h和失败:

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。你可以做到这一点有两种方法:

  1. #include <dshow.h>声明

  2. 在你的项目选项添加STRSAFE_NO_DEPRECATE的条件语句列表之前加入#define STRSAFE_NO_DEPRECATE到您的代码。在dshow.h

    About Strsafe.h

    • When you include Strsafe.h in your file, the older functions replaced by the Strsafe.h functions will be deprecated. Attempts to use these older functions will result in a compiler error telling you to use the newer functions. If you want to override this behavior, include the following statement before including Strsafe.h.

      #define STRSAFE_NO_DEPRECATE 
      
    • To allow only character count functions, include the following statement before including Strsafe.h.

      #define STRSAFE_NO_CB_FUNCTIONS 
      
    • To allow only byte count functions, include the following statement before including Strsafe.h.

      #define STRSAFE_NO_CCH_FUNCTIONS 
      

    另一种支持的解决方案是#include <dshow.h>所以之前定义NO_DSHOW_STRSAFE,这将不包括strsafe.h了,感谢这个代码:

该解决方案在MSDN上描述:

#ifndef NO_DSHOW_STRSAFE 
#define NO_SHLWAPI_STRFCNS 
#include <strsafe.h> 
#endif 
+0

感谢您清除东西... ... – Spektre

1

我没有这个版本的dshow.h和dstring.h,所以我不能自己检查它,但从你引用的错误消息看来,它似乎在dshow.h或其依赖关系中的某个地方,他们宣布“ sprintf“宏。你可以看看你是否可以找到它。

为了防止这种行为,你需要删除这个宏。使用

#undef sprintf 

后面的行包含dshow.h。

+0

非常感谢很多人在圈子里走了几个小时...... – Spektre

+0

有时很奇怪, SDK和VCL相互影响。这是来自BDS2006的dshow.h吗?我记得有一次我必须#undef StrToInt ... – JeffRSon

+0

是的,它来自BDS2006 Turbo C++ Explorer。链接的'strmiids.lib'来自DirectX9.2(BCB版本)并且可以工作。我并不熟悉DirectX只使用DInput,过去也使用DSound,但由于当时由于延迟和非工作回调导致无法使用,所以这种情况非常严重......但是,在BCB下有一些MSVC++风格的源代码可以带来一些乐趣,一些包括mes的定义和包括订单... – Spektre