1

我将花一点时间解释我的项目结构:

三个dll:

  1. mclController.dll - 用 C# 编写的用于控制硬件的第三方 dll。
  2. MCLWrapper.dll - 我用 C# 编写了这个 ll,这样它将作为 COM 工作,将 mclControl.dll 公开给原生 C++ dll。
  3. ThorDetectorSwitch.dll - 我用本机 C++ 编写了这个 dll。

结构:

  • ThorDetectorSwitch.dll 调用包装 mclController.dll 的 MCLWrapper.dll。
  • 我正在用 C++ 实现一个小型测试控制台应用程序 TDSTest.exe 来调用 ThorDetecttorSwitch.dll。

所以它基本上是这样工作的: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 的构造函数已编辑!于 2013 年 6 月 15 日,中部时间 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;
}

生成 COM 对象的 MCLWrapper

// 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是回报;

一些补充

  1. 我一直被告知这是因为CoInitialized()没有被调用,这就是原因,但我觉得这不是原因,因为这个 ThorDetectorSwitch.dll 与另一个应用程序完美配合,我相信我已经调用CoInitialized()了我的代码。
  2. 我已经注册了我的 MCLWrapper.dllregasm MCLWrapper.dll /tlb:MCLWrapper.tlb /codebase
  3. 调试器输出:“尝试在 OS 加载程序锁内进行托管执行。不要尝试在 DllMain 或图像初始化函数内运行托管代码,因为这样做会导致应用程序挂起。”

所以现在我不知道我应该往哪个方向走,而且我已经为这个问题苦苦挣扎了好几天。所以我真的希望有人能给我一些指点。谢谢!

4

1 回答 1

2

您需要懒惰地构造您的对象,而不是将其作为在 DLL 加载时创建的全局变量。

也许您可以让您的 DLL 提供一个Initialize()由客户端调用的函数?假设您当然不能使您的对象“根本不是全局的”。

于 2013-06-18T16:52:50.903 回答