Calling .NET dll from native C++
Asked Answered
C

2

8

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.

Cushing answered 14/5, 2013 at 15:2 Comment(7)
Have you tried to add a ComVisible attribute on the interface and class?Naevus
I think I have a COM visible attribute set as true in AssemblyInfo.cs. Let me paste it then you can see if it is what you are referring to.Cushing
Is it possible that you got the parameters on MCLSet_Switch wrong? &output looks like the address of a short but the function seems to want an int.Schwarzwald
The problem is, when I typed MySwitch->, it did not automatically show MCLSet_Switch(); And when I complied MCLWrapper, it said MCLSet_Switch() not recognized.Cushing
Ok it's good at assembly level. Maybe the namespace to use in C++ is not MCLWrapper, check the beginning of the .TLH file that has been created in the Debug or Release configuration directory by the #import directive.Naevus
Hi ALl: I solved the problem. I think I basically did two things: 1. Download there latest dll; 2. Create a project and clean pasted my old code. Somehow I got it work.Cushing
You can now decompile .NET DLLs with DotPeek.Lindo
C
2

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.

Cushing answered 14/5, 2013 at 16:43 Comment(0)
L
6
#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++.

Laboy answered 14/5, 2013 at 16:43 Comment(1)
Sorry, I think you are right, but I just got my problem fixed somehow. But I will keep your tips in mind. Thanks.Cushing
C
2

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.

Cushing answered 14/5, 2013 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.