2012-04-09 7 views
0

Ich arbeite an einem Projekt, das die Erstellung einer DLL beinhaltet, die eine bestimmte Schnittstelle honoriert, um in irgendeine Software zu stecken, um Funktionalität hinzuzufügen. Dies geschieht durch eine DLL, die meine DLL aufruft (ich habe nicht den Quellcode für die DLL, die den Aufruf ausführt). Ursprünglich erhielt ich eine Schnittstelle und eine C# Implementierung, die eine sichtbare COM-DLL erzeugte. Nachdem ich dies für eine Weile benutzt hatte, fand ich heraus, dass ich einige große C++ - Bibliotheken verwenden wollte und das Erstellen von Wrappern würde lange dauern, bis ich darüber nachdachte, eine C++ ATL COM-DLL zu erstellen. Ich tat dies und die Methoden meiner Klasse scheinen korrekt aufgerufen zu werden (ich registriere meine DLL, führe das Programm aus und die Methoden scheinen in der richtigen Reihenfolge aufgerufen zu werden), aber ich habe festgestellt, dass das Verhalten etwas anders ist.Warum zeigen meine C# - und C++ - DLLs ein unterschiedliches Verhalten?

Ich bin mir nicht sicher, wie ich das erklären soll, da mein Code sich auf eine Closed-Source-API bezieht, aber wenn ich ein Beispiel beschreibe, könnte jemand Ideen haben, wo ich hinschauen möchte.

Zum Beispiel in der C# dll ich versuche, diese eine Datei zu öffnen, indem Sie:

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(); 

ich die richtige Anzahl von Proben erhalten.

In meinem C++ dll ich diese haben (mit einigen der HRESULT Kontrollen entfernt, um den Code kürzer zu halten):

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(); 

aber die Dateien nicht richtig öffnen, was ist Null-Proben.

Mit OLEVIEW schaute ich auf die typelib und es sagt, das für die Funktion:

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

Die Datei ich Informationen erhalten aus ist eine, die während eines Experiments geschrieben wird und kurz bevor es mehr Daten erhält es ruft meine Methode auf und ich sollte in der Lage sein, die neueste Datei zu erhalten. In der C# -Dll ist dies möglich, in der C++ - DLL ist dies jedoch nicht der Fall. Während ich merke, dass die Besonderheiten davon verborgen sind, frage ich mich, ob irgendjemand irgendeine Idee hat, warum eine C++ COM DLL und eine C#, kompatible DLL, die die gleiche Schnittstelle benutzen, ein anderes Verhalten zeigen würden, wenn sie von derselben DLL aufgerufen werden.

Ich bin in diesem Moment ziemlich ratlos, also würden alle Ideen geschätzt werden, selbst wenn sie sich als sehr schlecht erweisen. Ich kann meinen Quellcode teilen, wenn jemand denkt, dass er Ihnen helfen könnte.

EDIT: Ich versuchte die Lösung, um 1 zu beantworten, aber ich konnte meinen Code nicht kompilieren. Auf die Frage nach der Lektüre dieses fand ich diesen Beitrag: Differences between [in, out] and [out, retval] in COM IDL definitions , dass dieser Zeiger, da die FMANFile zu vorschlagen scheint markiert [out, retval], dass das Verfahren wird:

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

oder bin ich falsch interpretiert diesen Artikel?

EDIT 2: Habe es funktioniert, obwohl ich nicht wirklich sicher bin warum. Ursprünglich hatte ich die Variablen im Header als private Membervariablen der Klasse deklariert, wie folgt aus:

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; 
}; 

einfach, es zu versuchen ich sie an die Spitze der Klasse delcaration wie folgt bewegt:

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

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

Ich dachte, dass diese auch private Mitglieder und die gleichen wie zuvor sind, so dass ich nicht erklären kann, warum dies zu funktionieren schien. Kann jemand das erklären?

Antwort

0

Ihr C++ Code korrekt ist, mit Ausnahme der folgenden Zeile:

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

Es spielt kein sens machen, weil ipFMANFile in der nächsten Anweisung erneut initialisiert wird.

Leider ist diese IDL-Deklaration:

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

ist für Debugging-Zwecke beschränkt, da es nicht die native COM mechanisme für das Exception Reporting über HRESULT unterstützt. Die COM-konforme Erklärung wäre:

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

Ich glaube, dass Sie nicht in der Lage sind die Bibliothek des Code zu ändern, so empfehle ich Ihnen einige externen Debugging-Tools wie ‚procmon.exe‘ zu versuchen und ‚dbgview.exe‘ die inspizieren Anwendungsereignisse beim Ausführen des CPP-Testfalls. Suchen Sie nach allen fehlgeschlagenen Aktionen.

Ich hoffe, das wird dir irgendwie helfen

+0

Danke für den Rat über diese Tools und klärende dies. Ich werde versuchen, sie jetzt zu benutzen. – Travis

Verwandte Themen