Consuming C#(dll) functions in a C/C++ project

Asked

Viewed 2,694 times

8

I need to call/reuse some functions I have in a DLL, developed in C#, within a project done in C.

I already looked for some things and what I managed to make it work was this project: http://support.microsoft.com/kb/828736

This article, step by step, describes how to call a DLL in native C++ . It works cool.

My problem is that this process uses Windows registry and .tlb. file generation.This is causing me a lot of problem as when I make any changes to my DLL, the program in C stops working, even recompiling everything.

So looking I found this other method: http://code.msdn.microsoft.com/windowsdesktop/Consuming-C-Library-in-937458e5

It explains how to consume a C# library in C/C++ without the use of export and import . tlb (which would give me the least headache).

I believe this second method is more efficient and has a much better interface.

The problem is that this second method is much more complicated and I don’t have a very large domain in C/C++. I wonder if anyone’s been through this problem and could give me a hand.

2 answers

5

I already had to do this, and I used a slightly different approach (I tested this procedure in Visual Studio 2012 and 2013).

For the test, I created a DLL in C#, called Bibliotecacsharp.dll, with the following class and namespace:

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

namespace BibliotecaCSharp
{
    public class Teste
    {
        public int Soma(int a, int b)
        {
            return a + b;
        }
    }
}

Now, on the C++ side, on another project, to run a code from a library in . Net (be C#, VB etc), the C++ project must be configured to support CLR, as shown in the figure:

Configuração do projeto

Once the project is configured, it is necessary to import the necessary libraries, which is done inside the file stdafx.h of your project in C++, simply add these lines to it:

//Includes e bibliotecas específicas do runtime para .Net
#include <mscoree.h>
#include <vcclr.h>
#pragma comment(lib, "mscoree.lib")

From now on, it is possible to instantiate classes written in C#, or VB.Net directly from within the C code++.

This example project in C++ is a simple console application with only one cpp file, but serves to demonstrate the technique:

#include "stdafx.h"

//Em todos os arquivos que forem acessar a classe, deve-se
//importar as bibliotecas e namespaces
#using <mscorlib.dll>
#using "<CAMINHO DA DLL EM C#>\BibliotecaCSharp.dll"

using namespace System;
using namespace BibliotecaCSharp;

int SomaCSharp(int a, int b)
{
    //Cria uma instância da classe desejada
    Teste^ t = gcnew Teste();

    return t->Soma(a, b);
}

int _tmain(int argc, _TCHAR* argv[])
{
    int s = SomaCSharp(1, 2);

    _tprintf(TEXT("Soma em C#: %d\n"), s);

    return 0;
}

However, the way it is, the C++ code will give error during execution, because the #using "<CAMINHO DA DLL EM C#>\BibliotecaCSharp.dll" is only for the compiler to locate the library, and nay for the program to locate the library when running.

To this end, I always copy the dll in C# to the same folder as the C++ executable, as shown in the figure below:

Arquivos na pasta

It would be possible to copy to another folder as long as it is in PATH system, but I find the solution of using the same folder simpler.

Just out of curiosity, this copy can be automated through Post-build Event command line, as the figure shows:

Post-build event command line

  • IS necessary create the class with gcnew in this case? Or it would work without problems with the class created in the stack?

  • 1

    Yes, one should use the gcnew, whenever the instantiated class is Managed. This way the object that goes to the Managed heap, where the Garbage Collector can act. If you use only new, the object would go to the normal heap of the system, and the Garbage Collector would not be able to monitor it. To avoid this, the compiler no longer even allows the compilation of a code with the build new Classe(), where Classe is a Managed class.

1

To prevent changes to your DLL written in C# from having an effect on your C++ program, preventing it from working properly, try to fix the global identifier of your module using the instructions in this link.

Behold:

// 
// declare FilgraphManager as a COM coclass 
// 
[ComImport, Guid("E436EBB3-524F-11CE-9F53-0020AF0BA770")] 
class FilgraphManager
{ 
}

Public interface names should not be changed either.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.