Я потрачу немного времени на объяснение структуры моего проекта:
Есть три библиотеки:
Состав:
Так что это в основном работает так: TDSTest.exe -> ThorDetectorSwitch.dll -> MCLWrapper -> mclController.dll
Некоторый код:
-Как TDSTest.exe (консольное приложение Windows, созданное с конфигурацией x64) вызывает ThorDetectorSwitch.dll:
#include "stdafx.h"#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <math.h>
#include <windows.h>
#include "TDSTest.h"
typedef long (*TDSFindDevices)(long&);
typedef long (*TDSGetParam)(const long, double&);
typedef long (*TDSTeardownDevice)();
typedef long (*TDSStartPosition)();
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
if (argc < 2)
{
cout<<"This is ThorDetecttorSwitch test program."<<endl;
return 1;
}
HINSTANCE hInst = LoadLibrary(_T(".\\Modules_Native\\ThorDetectorSwitch.dll"));
if( hInst == NULL )
{
DWORD err = GetLastError();
cout<<"Error loading ThorDetectorSwitch.dll. Program exiting..."<<endl;
return 1;
}
}
-Конструктор ThorDetectorSwitch.dll Editted! 15.06.2013, Центральное время 19:41
ThorDetectorSwitch::ThorDetectorSwitch() :_mcSwitch(ComHelper(__uuidof(MCLControlClass)))
{
CoInitialize(NULL);
MCLWrapper::MCLControlPtr mclSmartPtr;
HRESULT hr = CoCreateInstance(__uuidof(MCLWrapper::MCLControlClass), NULL, CLSCTX_ALL, __uuidof(MCLWrapper::MCLControl), (void**)&mclSmartPtr); // program breaks right here!!!
_mcSwticth = mclSmartPtr;
_A = WstringToBSTR(L"A");
_B = WstringToBSTR(L"B");
_C = WstringToBSTR(L"C");
_D = WstringToBSTR(L"D");
_deviceDetected = FALSE;
}
MCLWrapper, который делает COM-объект
// C# COM wrapper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mcl_RF_Switch_Controller64;
using System.Runtime.InteropServices;
// for function reference see miniCircuit RF controller manual
namespace MCLWrapper
{
[Guid("7C312A7C-2E77-4de7-A76F-990F268AB818")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface MCLControl
{
[DispId(1)]
void Connect(string SerialNumber);
[DispId(2)]
void Set_Switch(string SwitchName, int Val);
[DispId(3)]
void Set_SwitchesPort(byte binVal);
[DispId(4)]
void GetSwitchesStatus(int statusRet);
[DispId(5)]
void Disconnect();
};
[Guid("BEC33A1D-BB98-4332-B326-92D480ECC246"),
ClassInterface(ClassInterfaceType.None)]
public class MCLControlClass : MCLControl
{
private USB_RF_SwitchBox _sb = new USB_RF_SwitchBox();
public void Connect(string SerialNumber)
{
_sb.Connect(ref SerialNumber);
}
public void Set_Switch(string SwitchName, int Val)
{
_sb.Set_Switch(ref SwitchName, ref Val);
}
public void Set_SwitchesPort(byte binVal)
{
_sb.Set_SwitchesPort(ref binVal);
}
public void GetSwitchesStatus(int statusRet)
{
_sb.GetSwitchesStatus(ref statusRet);
}
public void Disconnect()
{
_sb.Disconnect();
}
}
}
Моя проблема:
Когда TDSTest выполняется, он сначала попадает
HINSTANCE hInst = LoadLibrary(_T(".\\Modules_Native\\ThorDetectorSwitch.dll"));
тогда это ломается в:
hr = CoCreateInstance(......)
в ThorDetectorSwitch.cpp
hr = -858993460
это возвращение;
Несколько дополнений
CoInitialized()
не был вызван, и это причина, но я чувствую, что это не причина, потому что этот ThorDetectorSwitch.dll прекрасно работает с другим приложением, и я полагаю, что я вызвал CoInitialized()
в моем коде.regasm MCLWrapper.dll /tlb:MCLWrapper.tlb /codebase
Так что сейчас я понятия не имею, в каком направлении мне идти, и я боролся с этой проблемой в течение многих дней. Поэтому я очень надеюсь, что кто-то может дать мне несколько советов. Спасибо!
Вам нужно лениво создавать свой объект, а не создавать его как глобальную переменную, создаваемую при загрузке DLL.
Может быть, вы могли бы сделать так, чтобы ваша DLL Initialize()
функция, которая будет вызвана клиентом? Предполагая, что вы не можете сделать свой объект «вообще не глобальным», конечно.
Других решений пока нет …