Question

I will spend a little time explaining my project stucture:

There are three dlls:

  1. mclController.dll - a third party dll written in C# to control the hardware..
  2. MCLWrapper.dll - I wrote this ll in C# such that it will be working as a COM to expose the mclControl.dll to a native C++ dll.
  3. ThorDetectorSwitch.dll - I wrote this dll with native C++.

Structure:

  • The ThorDetectorSwitch.dll calls the MCLWrapper.dll which wraps mclController.dll.
  • I am implementing a small testing console application in C++, TDSTest.exe to call ThorDetecttorSwitch.dll.

So it basically works like this: TDSTest.exe -> ThorDetectorSwitch.dll -> MCLWrapper -> mclController.dll

Some code:

-How TDSTest.exe (Windows console application, built with x64 configuration) calls 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;
        }

}

-Constructor of the ThorDetectorSwitch.dll EDITTED! on 06/15/2013, Central Time 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;
}

The MCLWrapper that makes a COM object

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

My Problem:

When the TDSTest is executed, it first hits

HINSTANCE hInst = LoadLibrary(_T(".\\Modules_Native\\ThorDetectorSwitch.dll"));

then it breaks at: hr = CoCreateInstance(......) in the ThorDetectorSwitch.cpp

hr = -858993460 is the return;

A few additionals

  1. I am kept be told it was because CoInitialized() did not get called, and that is the reason, but I feel that is not the reason because this ThorDetectorSwitch.dll works perfectly fine with another application, and I beleive I have called CoInitialized() in my code.
  2. I have registered my MCLWrapper.dll with regasm MCLWrapper.dll /tlb:MCLWrapper.tlb /codebase
  3. Debugger output: "Attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initalization function since doing so can cause the application of hang."

So right now I have no idea what direction I should go, and I have been struglling with this problem for days. So I really hope someone can give some pointers for me. Thanks!

Was it helpful?

Solution

You need to lazily construct your object instead of have it as a global variable created on DLL load.

Maybe you could have your DLL provide an Initialize() function that would be called by the client? Assuming you can't make your object "not global at all" of course.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top