【发布时间】:2012-04-22 04:33:51
【问题描述】:
我正在开展一个项目,该项目涉及创建一个支持特定接口的 dll,以便插入某些软件以向其添加功能。这是由调用我的 dll 的 dll 完成的(我没有执行调用的 dll 的源代码)。最初,我得到了一个接口和一个创建 COM 可见 dll 的 C# 实现。然而,在使用了一段时间后,我发现我想使用一些大型 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 中,我有这个(删除了一些 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 的解决方案,但是我无法编译我的代码。在阅读有关此内容时,我发现了这篇文章: Differences between [in, out] and [out, retval] in COM IDL definitions 这似乎表明,由于 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;
我认为默认情况下这些也是私有成员,并且和以前一样,所以我无法解释为什么这似乎有效。有人可以解释一下吗?
【问题讨论】:
标签: c++ visual-c++ dll com atl