3

I have C# DLL and I am using that DLL in C++ with the help of COM Interop by importing the corresponding .tlb file in my .cpp file #import "com.MyIntrop.tlb" and its working absolutely fine.

Now I want to use same DLL in my C code but because I can not use #import in C how to use same DLL which I have register as COM assembly in C.

Andrew Paes
  • 1,940
  • 1
  • 15
  • 20
SB1589
  • 41
  • 1
  • 2
    Where is the issue? Just get a header file from the IDL. – leppie Jan 09 '14 at 09:25
  • 1
    Same way you would use any COM object in C anyway [here](http://www.codeproject.com/Articles/632616/How-to-use-NET-Csharp-COM-objects-in-plain-C) a very small example. – Adriano Repetti Jan 09 '14 at 09:27
  • Googled a few answers maybe this one will do some help. http://stackoverflow.com/questions/728325/can-you-call-a-c-sharp-dll-from-a-c-dll – CrazyBean Mar 21 '14 at 00:44
  • From past experiences I would recommend you to either recode the function in C or migrate to C#. Years ago, I spent a lot of time trying to get my C code to call managed code. I got it working but after a few years and with heaps of changes, the call form C to managed dll broke and I can't seem to remember what I did to get it to work previously. From memory you need to 1) have COMVisible attribute, 2) use strong named assembly, 3) generate the .tlb file, 4) add the dll to GAC, 5) register the .tlb with regsvr – Tien Dinh Dec 27 '14 at 18:29
  • btw, we end up rewrite in c# so it can be maintain by other developers – Tien Dinh Dec 27 '14 at 18:31

1 Answers1

0

Here is a simple example with 3 files

  1. DLL in C#
  2. interface program in C++/CLR
  3. main program in C++

First the C# DLL. This will be built as a DLL.

using System;
using System.Collections.Generic;
using System.Text;

namespace csdll
{
   public class ReturnValues
   {
      public void CSGetInt(ref int x)
      {
         x = 42;
      }

      public void CSGetStr(ref string s)
      {
         s = "Hey it works";
      }
   }
}

Now the interface program. This is the glue logic. This has to be compiled as C++/CLR but can be in the same project as main: just not in the same file as it has to be compiled differently. Under General in Common Language Runtime Support, select Common Language Runtime Support (/clr).

#include <string>
#include <msclr\marshal_cppstd.h>
#using "csdll.dll"
using namespace System;

extern void cppGetInt(int* value)
{
   csdll::ReturnValues^ rv = gcnew csdll::ReturnValues();
   rv->CSGetInt(*value);
}

extern void cppGetStr(std::string& value)
{
   System::String^ csvalue;
   csdll::ReturnValues^ rv = gcnew csdll::ReturnValues();
   rv->CSGetStr(csvalue);
   value = msclr::interop::marshal_as<std::string>(csvalue);
}

Now the main program.

#include "stdafx.h"
#include <iostream>
#include <string>

// These can go in a header
extern void cppGetInt(int* value);
extern void cppGetStr(std::string& value);

int _tmain(int argc, _TCHAR* argv[])
{
   int value = 99;
   std::string svalue = "It does not work";
   cppGetInt(&value);
   std::cout << "Value is " << value << std::endl;
   cppGetStr(svalue);
   std::cout << "String value is " << svalue << std::endl;
   return 0;
}

Set the dependency to the DLL. Set the build platform to Mixed Platforms not win32 or any CPU. If it is set to any of those, something won't build. Run it and you will get

Value is 42
String value is Hey it works
cup
  • 7,589
  • 4
  • 19
  • 42