0

私は、機能を追加するためにいくつかのソフトウェアにプラグインするために、特定のインターフェイスを尊重するdllの作成を含むプロジェクトに取り組んでいます。これは、自分のdllを呼び出すdllによって実行されます(呼び出しを行うdllのソースコードがありません)。もともと私は、COM可視dllを作成するインターフェイスとC#実装を与えられました。ただし、これをしばらく使用した後、いくつかの大きなC ++ライブラリを使用したいと思いました。ラッパーの作成には長い時間がかかるため、代わりにC ++ ATLCOMdllを作成することを考えました。これを実行すると、クラスのメソッドが正しく呼び出されたように見えます(dllを登録し、プログラムを実行すると、メソッドが正しい順序で呼び出されたように見えます)が、動作の一部が異なることがわかりました。

私のコードはクローズドソースAPIに関連しているため、これを説明する方法がわかりませんが、例を説明すると、誰かが私がどこを見たいかについていくつかのアイデアを持っている可能性があります。

たとえば、C#dllでは、次のようにしてファイルを開こうとします。

FMANFileControl fileControl = new FMANFileControl();
FMANFile wFile = null;
const string filePath = @"C:\Data\April 4\Data_IDA.wiff";
wFile = fileControl.GetFileObject(filePath, 1);
long numSamples = wFile.GetNumberOfSamples();

正しい数のサンプルを取得します。

私のC++dllには、これがあります(コードを短くするために、HRESULTチェックの一部が削除されています)。

std::string filePath = "C:\\Data\\April 4\\Data_IDA.wiff";
_bstr_t fileName(filePath.c_str());
IFMANFilePtr ipFMANFile;
IFMANFileControlPtr ipFMANFileControl;
hr = ipFMANFileControl.CreateInstance(__uuidof(FMANFileControl));
hr = ipFMANFile.CreateInstance(__uuidof(FMANFile));
ipFMANFile = ipFMANFileControl->GetFileObject(fileName, 1);
long numSamples = ipFMANFile->GetNumberOfSamples(); 

ただし、ファイルは正しく開かないため、サンプルはゼロになります。

oleviewを使用して、typelibを調べたところ、関数について次のように表示されています。

[id(0x00000001), helpstring("method GetWiffFileObject")] 
IFMANWiffFile* GetWiffFileObject( [in] BSTR WiffFileName, [in] long sample); 

私が情報を取得するファイルは、実験中に書き込まれているファイルであり、さらにデータを取得する直前にメソッドを呼び出し、最新のファイルを取得できるはずです。C#dllではこれは可能ですが、C++dllでは不可能です。これの詳細は隠されていることに気づきますが、同じインターフェイスを使用するC ++ COM dllとC#のcomvisible dllが、同じdllによって呼び出されたときに異なる動作を示す理由を誰かが知っているのではないかと思います。

私は現時点でかなり困惑しているので、たとえそれらがベースから大きく外れていることが判明したとしても、どんなアイデアでもありがたいです。誰かが助けてくれるかもしれないと思ったら、ソースコードを共有することができます。

編集:私は答え1の解決策を試しましたが、コードをコンパイルできませんでした。これについて読んだとき、私はこの投稿を見つけました: COM IDL定義の[in、out]と[out、retval] の違いは、FMANFileポインターが[out、retval]とマークされているため、メソッドが次のようになることを示唆しているようです。

IFMANFilePtr ExploreData::IFMANFileControl(BSTR filename, long sample);

または私はその記事を誤解していますか?

編集2:理由はよくわかりませんが、機能しました。もともと私は、次のように、クラスのプライベートメンバー変数としてヘッダーで宣言された変数を持っていました。

class ATL_NO_VTABLE CUserIDA :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CUserIDA, &CLSID_UserIDAObject>,
public IUserIDA
{
.
.
.
public:
STDMETHOD(GetSwitchCriteria)(DOUBLE* intensity, DOUBLE* minMass, DOUBLE* maxMass, VARIANT_BOOL *selectIntensity, LONG* numOfDepCycles);
    .
    .
    .
private:
    ExploreDataObjects::IFMANWiffFilePtr ipFMANWiffFile;
ExploreDataObjects::IFMANWiffFile2Ptr ipFMANWiffFile2;
};

それを試すために、私はそれらを次のようにクラスのトップに移動しました:

class ATL_NO_VTABLE CUserIDA :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CUserIDA, &CLSID_UserIDAObject>,
public IUserIDA
{

ExploreDataObjects::IFMANWiffFilePtr ipFMANWiffFile;
ExploreDataObjects::IFMANWiffFile2Ptr ipFMANWiffFile2;

デフォルトでは、これらもプライベートメンバーであり、以前と同じだと思っていたので、なぜこれが機能しているように見えるのか説明できません。誰かがこれを説明できますか?

4

1 に答える 1

0

次の行を除いて、C++ コードは正しいです。

hr = ipFMANFile.CreateInstance(__uuidof(FMANFile));

ipFMANFile は次のステートメントでもう一度初期化されるため、意味がありません。

残念ながら、この IDL 宣言:

IFMANWiffFile* GetWiffFileObject([in] BSTR WiffFileName, [in] long sample); 

HRESULT を介した例外レポートのネイティブ COM メカニズムをサポートしていないため、デバッグ目的に制限されています。COM 準拠の宣言は次のようになります。

HRESULT GetWiffFileObject([in] BSTR WiffFileName, [in] long sample, [out, retval] IFMANWiffFile** fileInstance); 

ライブラリのコードを変更できないと思われるので、'procmon.exe' や 'dbgview.exe' などの外部デバッグ ツールを試して、CPP テスト ケースを実行するときにアプリケーション イベントを調べることをお勧めします。失敗したすべてのアクションを探します。

これが何らかの形で役立つことを願っています

于 2012-04-10T07:04:59.617 に答える