ATL COM DLL 适用于 C#,但不适用于 C++

发布于 2025-01-06 13:53:21 字数 2835 浏览 1 评论 0原文

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

我使用 ATL 创建了一个 dll,并试图让它与我提供的测试程序一起工作。我不想改变它访问 dll 的方式,因为这是固定的。我基于以前的 C# 版本构建了 dll,并尝试保持 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();

现在 sleep 函数位于 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;
}

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

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

EDIT: I have included a link to the code for my ATL COM dll, the test application and my original C# dll. As this is a complex project it might be the easiest solution. I am pretty desperate as I have not been able to find a solution myself.
Here is the link, if anyone wants to take a look:
https://docs.google.com/open?id=0B3ehFEncKJH7ZDgxMGI1YjgtZTE2MS00ZTBkLWI2NzgtYzVhZjUxOWEzZGI0

I created a dll using ATL and was trying to get it to work with a test program I was given. I do not want to change the manner in which it accesses the dll as this is fixed. I based the dll on a previous C# version and tried to keep the ProgIDs and UUIDs the same.

I have been having problems with a buffer overrun when I try to use any of the methods. However I have run into another problem and I have no idea why it is occurring. In order to make sure my dll was working I added a sleep statement to one of the methods. When I call this method from my test program, written in unmanaged c++, the sleep function does not appear to work. However, if I create a C# application and add my dll as a reference and call the method it does work. Does anyone have any idea why this might happen?

Edit:
I thought I should include some more details about how it was being used. The test c++ application creates and instance of the object like this:

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

right now the sleep function is in OnInitIDA.

When using C# I added a reference to the DLL and did this:

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

When I try to use GetChargeStatParam in the c++ application I get a buffer overrun but this does not happen in the C# version. But I digress...
In this case the C# application sleeps for 10 seconds.

I just do not know where to even begin looking in order to figure out why it does not work.

EDIT: This is the interface that is defined in the 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);

this is the implementation of OnInitIDA

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

Should I be concerned about how the UserIDA is defined in my dll? My previous C# dll that had the same methods worked fine with this test application.

EDIT:
Strangely enough I have found some rather strange behaviour that might give someone an idea though it puzzles me. I used the "Step Into" feature of VS2008 and found that when OnInitIDA is called it actually steps into another method GetInclusionList. If I put some code in this method it gets run. I also imagine this kind of behavior could cause a buffer overrun though I am not sure why this is actually happening.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自在安然 2025-01-13 13:53:21

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

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

不要将任何内容传递给 CoInitialize。来自 MSDN

参数

pvReserved [输入,可选] 

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

Hard to say. You might want to post the code for OnInitIDA.

You do have a bug that may or may not be related:

Don't pass anything to CoInitialize. From MSDN :

Parameters

pvReserved [in, optional] 

This parameter is reserved and must be NULL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文