2016-10-12 4 views
1

最終的にビデオキャプチャクラスをアップグレードする時間がありました。私はVFW(今まで私が使っていたもの)とDirectShowを比較したかったのです。予想通り、DirectShowは高速ですが、情報テキストを追加すると、AnsiString::sprint()はもはやAnsiStringのメンバーになりません。DShow.hを含むことでVCL AnsiString :: sprintf()がBDS2006に壊れています

いくつかの苦労の末、私は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++; 
} 
//--------------------------------------------------------------------------- 

それはそれで一つのTTimerとの単純なVCLフォームアプリです。 TTimerは、カウンタ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.hnamespaceに入れることも役に立ちません。

誰にも手がかりがありますか?

Q1。これを修正するには?

Q2。 What/whereは正確にこれを引き起こしていますか?

私は考えることができ、かつ動作するはず唯一の解決策(私は私ができるならば、それを避けたい)、OBJ(またはDLL)を作成することですDirectShowのものとし、それを標準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_DEPRECATE

DEPRECATE_SUPPORTED両方が(この状況における場合である)定義されていない場合、#define sprintfの使用は、コンパイル時sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;として見るべきあらゆる種類sprintfのシンボルに後続のすべての参照を引き起こします。

コンパイルエラーが発生するのはこのためです。 vcl.hstrsafe.h前に含まれている場合、dstring.hは、まず含まれますので、コンパイラは見正しいAnsiString::sprintf()メソッドの宣言、その後strsafe.hAnsiString().sprint("%i",i)へのあなたの呼び出しがあるので、コンパイラは、あなたのTimer1Timer()コードを見る前(おそらくUnit1.hで)含まれます実際にAnsiString().sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;("%i",i)に電話しようとしましたが、失敗しました。

あなたはvcl.hdshow.h含んを交換するときdstring.hが含まれ、そのコンパイラはdstring.hAnsiString::sprintf()方法については、以下の宣言を見て、失敗する前に、strsafe.h#define sprintfステートメントが処理されます:

AnsiString& __cdecl   sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;(const char* format, ...); // Returns *this 

ないようにするにはこの動作は、 の文を使用して#include <dshow.h>の後、JeffRSonのように示唆しました。しかし、が正しい解決策はの前にSTRSAFE_NO_DEPRECATEを定義することです。

  1. あなたのプロジェクトオプションで条件文リストにSTRSAFE_NO_DEPRECATEを追加する#include <dshow.h>ステートメントの前に、あなたのコードに

  2. #define STRSAFE_NO_DEPRECATEを追加:あなたはいずれかの方法でそれを行うことができます。

このソリューションは、MSDNで説明されています

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 
    

別のサポートソリューションは、それがdshow.hで、もうこのコードのおかげでstrsafe.hを含まないように#include <dshow.h>NO_DSHOW_STRSAFEを定義することです:

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

物事をクリアするためのおかげで... – Spektre

1

私はこのバージョンのdshow.hとdstring.hを持っていないので、自分ではチェックすることはできませんが、エラーメッセージから、dshow.hまたはその依存関係のどこかに " sprintf "マクロ。あなたがそれを見つけることができるかもしれません。

この動作を防止するには、このマクロを削除する必要があります。 dshow.hを含む行の後に、

#undef sprintf 

を使用してください。

+0

ありがとうございましたたくさんありがとうございました... – Spektre

+0

SDKとvclは互いに影響を与えます。これはBDS2006のdshow.hですか?私は#undef StrToIntにしなければならなかったことを覚えています... – JeffRSon

+0

はい、BDS2006 Turbo C++ Explorerからです。リンクされた 'strmiids.lib'はDirectX9.2(BCBバージョン)のもので、動作します。私はDirectXだけでDInputを使い慣れていませんでしたが、過去にはDSoundでしたが、待ち時間や非動作中のコールバックのために使用できなくなったのでバストでした...しかし、いくつかのMSVC++スタイルのソースでBCBといくつかは定義のmesであり、注文を含んでいます... – Spektre

関連する問題