Я пытаюсь создать COM dll, используя ATL, который совпадает с другим, который я изначально имел в C #.Этот dll обычно вызывается сторонним dll, для которого у меня нет исходного кода, поэтому я хотел, чтобы UUID были такими же, как и progID.У меня также есть тестовое приложение, которое вызывает методы в моей DLL, и именно так я его тестировал.Интерфейс, определенный тестовым приложением:
STDMETHOD(GetSwitchCriteria)(double* intensity, double* minMass, double* maxMass,
BOOL* selectIntensity, long* numOfDepCycles) = 0;
STDMETHOD(GetChargeStateParam)(short* minCharge, short* maxCharge, BOOL* doChargeState) = 0;
STDMETHOD(GetInclusionList)(double* intensity, double* theList, short* numOfItems) = 0;
STDMETHOD(GetExclusionList)(long* exRTWindow, double* theMassList, long* theRTList,
short* numOfItems) = 0;
STDMETHOD(GetOtherCriteria)(long* smartFilterTime, double* isoExclusionWin,
double* massTolerance, BOOL* isPPM) = 0;
STDMETHOD(GetIsotopeMatchParam)(double* theMassList, double* theAbundanceList,
short* numOfItems, double* abTolerance, double* maTolerance) = 0;
// called at the start of each IDA run
STDMETHOD(OnInitIDA)() = 0;
// called at the end of each survey scan
STDMETHOD(OnScreenSurveySpec)() = 0;
// called at the time of switch
STDMETHOD(OnPrepareNextScan)(double* selectedMasses, double* selectedIntensities, long* selectedCharges, int itemCount) = 0;
В моем новом dll, использующем ATL, я попытался имитировать это, и определения приведены ниже:
STDMETHOD(GetSwitchCriteria)(DOUBLE* intensity, DOUBLE* minMass, DOUBLE* maxMass, VARIANT_BOOL* selectIntensity, LONG* numOfDepCycles);
STDMETHOD(GetChargeStateParam)(SHORT* minCharge, SHORT* maxCharge, VARIANT_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, VARIANT_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);
Первоначально я использовал BOOL длянекоторые параметры, но я заметил, что C # dll использовал VARIANT_BOOL, когда я искал его в файле TLB.
Когда я вызываю два метода, которые не имеют параметров, я получаю HRESULT 0. То же самое делает дляметод OnPrepareNextScan.Однако, когда я звоню другим, я получаю исключение, переполнение буфера, и я не уверен, почему это так.У кого-нибудь есть идея, почему это происходит, или как я могу это исследовать?
Возможно, это связано с несовместимостью типов между типами, определенными в обоих интерфейсах, и, возможно, типами, которые я использую при создании переменных для использования сметод?Пример кода, используемого для вызова одного из методов:
short minCharge = 0;
short maxCharge = 0;
BOOL doChargeState = FALSE;
result = m_pUserIDA->GetChargeStateParam(&minCharge, &maxCharge, &doChargeState);
std::cout << "HRESULT of GetChargeStateParam: " << result << std::endl;
Пробовал долгое решение, упомянутое ниже, но, похоже, оно не помогло.
Я думал, что я должен опубликовать оригиналинтерфейс из C # dll.
[Guid("76F452FF-7A89-11d4-8A2C-00B0D023C6A0")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public unsafe interface IUserIDA
{
[DispId(1)]
void GetSwitchCriteria(ref double intensity, ref double minMass, ref double maxMass, ref bool selectIntensity, ref long numOfDepCycles);
[DispId(2)]
void GetChargeStateParam(ref short minCharge, ref short maxCharge, ref bool doChargeState);
[DispId(3)]
void GetInclusionList(ref double intensity, ref double theList, ref short numOfItems);
[DispId(4)]
void GetExclusionList(ref long exRTWindow, ref double theMassList, ref long theRTList, ref short numOfItems);
[DispId(5)]
void GetOtherCriteria(ref long smartFilterTime, ref double isoExclusionWin, ref double massTolerance, ref bool isPPM);
[DispId(6)]
void GetIsotopeMatchParam(ref double theMassList, ref double theAbundanceList, ref short numOfItems, ref double abTolerance, ref double maTolerance);
[DispId(7)]
void OnInitIDA();
[DispId(8)]
void OnScreenSurveySpec();
[DispId(9)]
void OnPrepareNextScan(double* selectedMasses, double* SelectedIntensities, long* selectedCharges, int itemCount);
}
Последний метод, OnPrepareNextScan, является единственным, который, кажется, работает, и вы можете видеть, что он определяется с помощью обычных указателей, а не операторов .NET ref, может ли это бытьпроблема?
Я подумал, что я мог бы также включить файлы Type Lib для каждого, возможно, разница в них позволит понять, в чем проблема и какие различия между ними:
Оригинальный C #dll:
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: AnalystIDA.dll
[
uuid(7ED40FB0-D178-47FA-9EF3-B434E0803D5F),
version(1.0),
custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "Analyst_UserIDA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=de4cf4f15e545467")
]
library Analyst_UserIDA
{
// TLib : // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
importlib("mscorlib.tlb");
// TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface IUserIDA;
interface _Utility;
[
uuid(CDD947DD-7B9E-382E-9F6F-55218F927C3A),
version(1.0),
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.Utility")
]
coclass Utility {
[default] interface _Utility;
interface _Object;
};
[
odl,
uuid(76F452FF-7A89-11D4-8A2C-00B0D023C6A0),
version(1.0),
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.IUserIDA")
]
interface IUserIDA : IUnknown {
HRESULT _stdcall GetSwitchCriteria(
[in, out] double* intensity,
[in, out] double* minMass,
[in, out] double* maxMass,
[in, out] VARIANT_BOOL* selectIntensity,
[in, out] int64* numOfDepCycles);
HRESULT _stdcall GetChargeStateParam(
[in, out] short* minCharge,
[in, out] short* maxCharge,
[in, out] VARIANT_BOOL* doChargeState);
HRESULT _stdcall GetInclusionList(
[in, out] double* intensity,
[in, out] double* theList,
[in, out] short* numOfItems);
HRESULT _stdcall GetExclusionList(
[in, out] int64* exRTWindow,
[in, out] double* theMassList,
[in, out] int64* theRTList,
[in, out] short* numOfItems);
HRESULT _stdcall GetOtherCriteria(
[in, out] int64* smartFilterTime,
[in, out] double* isoExclusionWin,
[in, out] double* massTolerance,
[in, out] VARIANT_BOOL* isPPM);
HRESULT _stdcall GetIsotopeMatchParam(
[in, out] double* theMassList,
[in, out] double* theAbundanceList,
[in, out] short* numOfItems,
[in, out] double* abTolerance,
[in, out] double* maTolerance);
HRESULT _stdcall OnInitIDA();
HRESULT _stdcall OnScreenSurveySpec();
HRESULT _stdcall OnPrepareNextScan(
[in, out] double* selectedMasses,
[in, out] double* SelectedIntensities,
[in, out] int64* selectedCharges,
[in] long itemCount);
};
[
uuid(5B2DBDD4-B763-428A-B48F-2E148138E7A4),
version(1.0),
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.UserIDAObject")
]
coclass UserIDAObject {
interface _Object;
[default] interface IUserIDA;
};
[
odl,
uuid(8094073C-362D-37BB-9791-E9D163271C73),
hidden,
dual,
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.Utility")
]
interface _Utility : IDispatch {
};
};
Моя новая dll:
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: AnalystIDA.dll
[
uuid(7ED40FB0-D178-47FA-9EF3-B434E0803D5F),
version(1.0),
helpstring("AnalystIDA 1.0 Type Library"),
custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 117441012),
custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1329510523),
custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, "Created by MIDL version 7.00.0500 at Fri Feb 17 15:28:38 2012
")
]
library AnalystIDALib
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface IUserIDA;
[
uuid(5B2DBDD4-B763-428A-B48F-2E148138E7A4),
helpstring("UserIDAObject Class")
]
coclass UserIDAObject {
[default] interface IUserIDA;
};
[
odl,
uuid(76F452FF-7A89-11D4-8A2C-00B0D023C6A0),
helpstring("IUserIDA Interface"),
dual,
nonextensible,
oleautomation
]
interface IUserIDA : IDispatch {
[id(0x00000001), helpstring("method GetSwitchCriteria")]
HRESULT GetSwitchCriteria(
[in, out] double* intensity,
[in, out] double* minMass,
[in, out] double* maxMass,
[in, out] VARIANT_BOOL* selectIntensity,
[in, out] long* numOfDepCycles);
[id(0x00000002), helpstring("method GetChargeStateParam")]
HRESULT GetChargeStateParam(
[in, out] short* minCharge,
[in, out] short* maxCharge,
[in, out] VARIANT_BOOL* doChargeState);
[id(0x00000003), helpstring("method GetInclusionList")]
HRESULT GetInclusionList(
[in, out] double* intensity,
[in, out] double* theList,
[in, out] short* numOfItems);
[id(0x00000004), helpstring("method GetExclusionList")]
HRESULT GetExclusionList(
[in, out] long* exRTWindow,
[in, out] double* theMassList,
[in, out] long* theRTList,
[in, out] short* numOfItems);
[id(0x00000005), helpstring("method GetOtherCriteria")]
HRESULT GetOtherCriteria(
[in, out] long* smartFilterTime,
[in, out] double* isoExclusionWin,
[in, out] double* massTolerance,
[in, out] VARIANT_BOOL* isPPM);
[id(0x00000006), helpstring("method GetIsotopeMatchParam")]
HRESULT GetIsotopeMatchParam(
[in, out] double* theMassList,
[in, out] double* theAbundanceList,
[in, out] double* abTolerance,
[in, out] double* maTolerance);
[id(0x00000007), helpstring("method OnInitIDA")]
HRESULT OnInitIDA();
[id(0x00000008), helpstring("method OnScreenSurveySpec")]
HRESULT OnScreenSurveySpec();
[id(0x00000009), helpstring("method OnPrepareNextScan")]
HRESULT OnPrepareNextScan(
[in, out] double* selectedMasses,
[in, out] double* selectedIntensities,
[in, out] long* selectedCharges,
[in] long itemCount);
};
};
Другая правка: Я замечаю, что ProgID Analyst_UserIDA.UserIDAObject не появляется в моей новой библиотеке DLL типа,Это используется для создания экземпляра UserIDAObject в тестовом приложении: IUserIDAPtr m_pUserIDA;:: CoInitialize (m_pUserIDA);m_pUserIDA.CreateInstance (_T ("Analyst_UserIDA.UserIDAObject"));
Больше прогресса / путаницы: Я решил посмотреть, есть ли проблема с DLL, создав проект C #, который быназовите это dll.Когда я сделал это, у меня возникли проблемы с работой.Я также заметил, что методы, которые, казалось, работали первоначально, не делают.Я добавил оператор сна к одному из них, и он никогда не выполняется при вызове моим тестовым приложением.