【问题标题】:ATL COM DLL works with C# but not with C++ATL COM DLL 适用于 C# 但不适用于 C++
【发布时间】:2012-03-09 21:49:07
【问题描述】:

编辑:我已经包含了一个指向我的 ATL COM dll、测试应用程序和我的原始 C# dll 的代码的链接。由于这是一个复杂的项目,它可能是最简单的解决方案。我非常绝望,因为我自己无法找到解决方案。 这是链接,如果有人想看一下: https://docs.google.com/open?id=0B3ehFEncKJH7ZDgxMGI1YjgtZTE2MS00ZTBkLWI2NzgtYzVhZjUxOWEzZGI0

我使用 ATL 创建了一个 dll,并试图让它与给定的测试程序一起工作。我不想更改它访问 dll 的方式,因为这是固定的。我将 dll 基于以前的 C# 版本并尝试保持 ProgID 和 UUID 相同。

当我尝试使用任何方法时,我一直遇到缓冲区溢出问题。但是我遇到了另一个问题,我不知道它为什么会发生。为了确保我的 dll 正常工作,我在其中一种方法中添加了 sleep 语句。当我从用非托管 c++ 编写的测试程序中调用此方法时,睡眠功能似乎不起作用。但是,如果我创建一个 C# 应用程序并将我的 dll 添加为引用并调用它确实有效的方法。有谁知道为什么会发生这种情况?

编辑: 我想我应该包括一些关于如何使用它的更多细节。测试 c++ 应用程序创建对象的实例如下:

IUserIDAPtr m_pUserIDA; 
::CoInitialize(m_pUserIDA);
m_pUserIDA.CreateInstance(_T("Analyst_UserIDA.UserIDAObject"));

if (m_pUserIDA != NULL)
{
    cout << "Aww yeah, that point isn't null" << endl;
    m_pUserIDA->AddRef();


    HRESULT result = m_pUserIDA->OnInitIDA();

现在睡眠功能在 OnInitIDA 中。

在使用 C# 时,我添加了对 DLL 的引用并这样做了:

        UserIDAObject IDAObject = new UserIDAObject();
        IDAObject.OnInitIDA();
        short minCharge = 0;
        short maxCharge = 0;
        bool doChargeState = false;
        IDAObject.GetChargeStateParam(ref minCharge, ref maxCharge, ref doChargeState);

当我尝试在 c++ 应用程序中使用 GetChargeStatParam 时,出现缓冲区溢出,但在 C# 版本中不会发生这种情况。但我离题了... 在这种情况下,C# 应用程序会休眠 10 秒。

我什至不知道从哪里开始寻找以找出它为什么不起作用。

编辑:这是在 dll 中定义的接口:

STDMETHOD(GetSwitchCriteria)(DOUBLE* intensity, DOUBLE* minMass, DOUBLE* maxMass, BOOL* selectIntensity, LONG* numOfDepCycles);
STDMETHOD(GetChargeStateParam)(SHORT* minCharge, SHORT* maxCharge, BOOL* doChargeState);
STDMETHOD(GetInclusionList)(DOUBLE* intensity, DOUBLE* theList, SHORT* numOfItems);
STDMETHOD(GetExclusionList)(LONG* exRTWindow, DOUBLE* theMassList, LONG* theRTList, SHORT* numOfItems);
STDMETHOD(GetOtherCriteria)(LONG* smartFilterTime, DOUBLE* isoExclusionWin, DOUBLE* massTolerance, BOOL* isPPM);
STDMETHOD(GetIsotopeMatchParam)(DOUBLE* theMassList, DOUBLE* theAbundanceList, DOUBLE* abTolerance, DOUBLE* maTolerance);
STDMETHOD(OnInitIDA)(void);
STDMETHOD(OnScreenSurveySpec)(void);
STDMETHOD(OnPrepareNextScan)(DOUBLE* selectedMasses, DOUBLE* selectedIntensities, LONG* selectedCharges, LONG itemCount);

这是 OnInitIDA 的实现

STDMETHODIMP CUserIDA::OnInitIDA(void)
{
// TODO: Add your implementation code here
Sleep(5000);
return S_OK;
}

我应该关心如何在我的 dll 中定义 UserIDA 吗?我以前使用相同方法的 C# dll 在这个测试应用程序中运行良好。

编辑: 奇怪的是,我发现了一些相当奇怪的行为,尽管它让我感到困惑,但它们可能会给某人一个想法。我使用了 VS2008 的“Step Into”功能,发现当调用 OnInitIDA 时,它实际上是进入了另一个方法 GetInclusionList。如果我在这个方法中加入一些代码,它就会运行。我也认为这种行为可能会导致缓冲区溢出,尽管我不确定为什么会发生这种情况。

【问题讨论】:

  • 你不需要AddRef你从CreateInstance得到的指针。
  • 根据您的编辑,我会说您的 VTABLE 搞砸了。最可能的原因是 C++ 与 C# 端的 IDAObject 接口定义不同。

标签: c++ visual-c++ dll com atl


【解决方案1】:

很难说。您可能想发布 OnInitIDA 的代码。

您确实有一个可能相关也可能不相关的错误:

不要将任何东西传递给CoInitialize。来自MSDN

参数

pvReserved [in, optional] 

此参数为保留参数,必须为NULL。

【讨论】:

  • 我可以调查一下,我没有创建原始测试应用程序,所以这些错误不是我做的,但我对 Windows 编程还是很陌生,不会发现它们。我将发布一些代码。但是现在 OnInitIDA 基本上是空的,只需要调用一次 Sleep。
  • 我确实尝试过更改它,但每次运行时都会导致缓冲区溢出。我应该注意到,当我创建这个 dll 的 C# 版本时,测试应用程序运行良好。我对这个 ATL 项目的目标是完全复制 dll 并创建一个可以由相同代码调用的 com dll。
  • 你能不能在你的睡眠语句中打断点。根据您到目前为止所介绍的内容,您的项目听起来有些问题。是用向导创建的 ATL exe 吗?
  • 我之前尝试过输入断点,但它似乎从未命中它。不过我会再试一次。它是使用向导创建的。我最近问了一些相关的问题,因为我遇到了很多问题,所以很多代码都分布在这些问题中。
  • 如果你不能在 atl dll 中打断点,那么还有一些与你的代码无关的事情,而是你的项目或环境。确保在 dll 项目中链接器设置寄存器输出设置为是,并且干净的构建不会显示错误 MSB8011。如果您确定您的 dll 已正确注册并且仍然无法命中断点,请尝试放置 ATLASSERT(false);在你的 init 方法中。那应该允许您附加调试器。还要确保您使用的是调试版本而不是发布版本。
猜你喜欢
  • 1970-01-01
  • 2021-02-25
  • 2011-09-26
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多