Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling .NET dll from native C++

I have a problem calling a .NET dll (mclNET.dll) using my COM wrapper. This is a third part dll which I do not have source code of. Basically I want to use this mclNET.dll in my pure native C++ application, so I am developing a C# wrapper. MCLWrapper.dll, that makes the methods in mclNET.dll visible. Here is what I did:

  • In MCLWrapper.dll, I added the mclNET.dll as reference, then define the interface to make the mclNET.dll methods visible. here is some of my code:

    using System;            
    using System.Collections.Generic;            
    using System.Linq;            
    using System.Text;           
    using mclNET;       
    
    namespace MCLWrapper       
    {            
         public interface MCLControl            
         {                
              void MCLConnect(string SerialNumber);                
              void MCLSet_Switch(string SwitchName, int Val);                
              void MCLDisconnect();         
         };
    
         public class MCLControlClass:MCLControl
         {
             private USB_RF_SwitchBox _sb = new USB_RF_SwitchBox();
    
             public void MCLConnect(string SerialNumber)
             {            
                 _sb.Connect(ref SerialNumber);
             }
    
             public void MCLSet_Switch(string SwitchName, int Val)
             {
                 _sb.Set_Switch(ref SwitchName, ref Val);
             }
    
             public void MCLDisconnect()
             {
                 _sb.Disconnect();
             }
         }
     }
    

And this is the AssemblyInfor.cs for MCLWrapper.dll:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MCLWrapper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MCLWrapper")]
[assembly: AssemblyCopyright("Copyright ©  2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//[assembly: AssemblyKeyFile("..\\MCLWrapper.SNK")]


// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("14fa8796-ee52-4e39-8481-f893ad92bb68")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
  • Then after I built this Wrapper.dll, I registered the it using regasm command, to generate a .tlb file

  • Then in my native C++ application, I imported the tlb file, and tried to use the Wrapper.dll which referred the NET.dll. Here is some code in native C++ application:

    #include "stdafx.h"
    #include "math.h"
    #include "DetectorSwitch.h"
    #include "DetectorSwitchSetupXML.h"
    #include "OleAuto.h"
    
    #import "C:/MyPath/MCLWrapper.tlb" raw_interfaces_only   
    
    wchar_t message[256];
    using namespace MCLWrapper;
    
    long DetectorSwitch::FindDevices(long &deviceCount)
    {
        long ret = TRUE;
    
        deviceCount=0;
    
           HRESULT hCoInitialize = CoInitialize(NULL);
    
        MCLControlPtr MySwitch(__uuidof(MCLControlClass));
    
        HRESULT hConnet = MySwitch->MCLConnect(_SN);    // connect to sc
    
        short output  = 1;
        MySwitch->MCLSet_Switch(&_A,&output);
    
    }
    

Now the problem is, it does not recognize MySwitch->MCLSet_Switch(&_A,&output) function, which means, the mclNET.dll is not fully exposed to my native C++ code yet.

I am wondering what is the problem here? How I can by any chance correct it? How exactly can I call a .NET dll in my native C++ application? Many thanks up front.

like image 450
Nick Tsui Avatar asked May 14 '13 15:05

Nick Tsui


2 Answers

#import <mscorlib.tlb> raw_interfaces_only
#import C:/MyPath/MCLWrapper.tlb" no_namespace named_guids

Try is above mentioned import statements - works for me and call your .net code without any namespaces from your native C++.

like image 118
Markus Schumann Avatar answered Oct 03 '22 06:10

Markus Schumann


I solved the problem finally. I think I basically did two things:

  1. Download there latest NET.dll;

  2. I created a new project "MCLWrapper" which generates a new MCLWrapper.dll and clean pasted the code from my old project.

Maybe there is something I messed up in my old project that I did not realize. Maybe it was the new NET.dll did the magic. I have no idea. I basically repeated what I have done, but this time pretty cleanly.

Somehow I got it work. So basically, my original thread is pretty much how to call a .NET dll from native C++ code. Hope my experience will be helpful for you.

like image 26
Nick Tsui Avatar answered Oct 03 '22 05:10

Nick Tsui