C++ 为什么我的C和C++;DLL表现出不同的行为?

C++ 为什么我的C和C++;DLL表现出不同的行为?,c++,visual-c++,dll,com,atl,C++,Visual C++,Dll,Com,Atl,我正在从事一个项目,该项目涉及创建一个dll,该dll支持某个接口,以便插入某些软件,以便向其添加功能。这是由调用我的dll的dll完成的(我没有进行调用的dll的源代码)。最初,我得到了一个接口和一个C#实现,它创建了一个COM可见dll。然而,在使用了一段时间后,我发现我想利用一些大型C++库,而创建包装器需要花费很长时间来考虑创建一个C++ ATL COM DLL。我这样做了,我的类的方法似乎被正确调用(我注册了我的dll,运行了程序,这些方法似乎被正确的顺序调用),但是我发现有些行为是不

我正在从事一个项目,该项目涉及创建一个dll,该dll支持某个接口,以便插入某些软件,以便向其添加功能。这是由调用我的dll的dll完成的(我没有进行调用的dll的源代码)。最初,我得到了一个接口和一个C#实现,它创建了一个COM可见dll。然而,在使用了一段时间后,我发现我想利用一些大型C++库,而创建包装器需要花费很长时间来考虑创建一个C++ ATL COM DLL。我这样做了,我的类的方法似乎被正确调用(我注册了我的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中,我有这个(用一些HEST检查程序删除,以便使代码更短):

但是文件没有正确打开,结果是零样本

我使用oleview查看了typelib,它对函数说:

[id(0x00000001), helpstring("method GetWiffFileObject")] 
IFMANWiffFile* GetWiffFileObject( [in] BSTR WiffFileName, [in] long sample); 
我从中获取信息的文件是在实验期间写入的文件,在它获取更多数据之前,它调用了我的方法,我应该能够获取最新的文件。在C++的DLL中,这是可能的,但是在C++ DLL中,这不是。虽然我意识到了这一点的细节,但我想知道,有没有人知道为什么使用同一个接口的C++ COM DLL和C语言可编辑DLL在被相同的DLL调用时会表现出不同的行为。 我现在很困惑,所以任何想法都会得到赞赏,即使它们被证明是非常离谱的。如果有人认为他们能提供帮助,我可以分享我的源代码

编辑: 我尝试了答案1的解决方案,但是我无法编译我的代码。读到这篇文章时,我发现了这篇文章: 这似乎表明,由于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;
class ATL\u NO\u VTABLE CUserIDA:
公共CComObjectRootEx,
公共课程,
公共IUserIDA
{
.
.
.
公众:
STDMETHOD(GetSwitchCriteria)(双*强度、双*最小质量、双*最大质量、变量\布尔*选择强度、长*numdepCycles);
.
.
.
私人:
ExploreDataObjects::IFMANWiffFilePtr ipFMANWiffFile;
ExploreDataObjects::IFMANWiffFile2Ptr ipFMANWiffFile2;
};
为了尝试,我将它们移到了类delcaration的顶部,如下所示:

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;
class ATL\u NO\u VTABLE CUserIDA:
公共CComObjectRootEx,
公共课程,
公共IUserIDA
{
ExploreDataObjects::IFMANWiffFilePtr ipFMANWiffFile;
ExploreDataObjects::IFMANWiffFile2Ptr ipFMANWiffFile2;

我认为默认情况下,这些都是私有成员,和以前一样,所以我无法解释为什么这似乎是可行的。有人能解释一下吗?

< p>你的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测试用例时检查应用程序事件。查找所有失败的操作


我希望这会对您有所帮助

谢谢您对这些工具的建议并对此进行了澄清。我现在就尝试使用它们。