0

I have to use C++ existing code in a new C# project. This C++ code is an unmanaged code contained in a DLL. One of my colleague already did this with "C" code, but in my case, my DLL contain a "Class" and I don't know if it is possible to do this.

What is the right way to use this C++ Class in my C# Application?

Update:

thanks for all theses answers. I tried do it with a simple class by following this article Using Unmanaged C Libraries DLLS in NET Application

My initial class is coded on Borland C++ Builder 6:

Test.cpp:

#include <basepch.h>
#pragma hdrstop
#include "Test.h"
#pragma package(smart_init)

__fastcall TTest::TTest() {
        //rien
}
__fastcall TTest::~TTest() {
        //rien
}
void __fastcall TTest::setNombre(int nbr) {
        nombre = nbr;
}
int __fastcall TTest::getNombre() {
        return nombre;
}

Test.h:

#ifndef TestH
#define TestH
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <string.h>
#include <stdio.h>
#include <StrUtils.hpp>
#include <time.h>

class PACKAGE TTest
{
private:
       int nombre;
protected:
public:
        __fastcall TTest();
        __fastcall ~TTest();
        void __fastcall setNombre(int nbr);
        int __fastcall getNombre();
};
extern PACKAGE TTest *Test;
#endif

The compilation of this class is OK :D

Then I tried to create the unmanaged class like in the article. But I have a problem to create this class in C++ Builder.

Unmanaged.cpp:

#pragma hdrstop
#include "Unmanaged.h"
#pragma package(smart_init)

struct UnmanagedClasseTest
{
        int nombre;

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@$bctr$qqrv", CallingConvention=CallingConvention::ThisCall)]
        static void ctor(UnmanagedClasseTest* c);

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@$bdtr$qqrv", CallingConvention=CallingConvention::ThisCall)]
        static void dtor(UnmanagedClasseTest* c);

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@setNombre$qqri", CallingConvention=CallingConvention::ThisCall)]
        static void setNombre(UnmanagedClasseTest* c, int nbr*);

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@getNombre$qqrv", CallingConvention=CallingConvention::ThisCall)]
        static int getNombre(UnmanagedClasseTest* c);

        static void Uctor(UnmanagedClasseTest* c) {
                ctor(c);
        }
        static void Udtor(UnmanagedClasseTest* c) {
                dtor(c);
        }
        static void UsetNombre(UnmanagedClasseTest* c, int i) {
                nombre = setNombre(c);
        }
        static int UgetNombre(UnmanagedClasseTest* c) {
                return getNombre(c);
        }
};

Unmanaged.h:

#ifndef UnmanagedH
#define UnmanagedH

static void ctor(UnmanagedClasseTest* c);
static void dtor(UnmanagedClasseTest* c);
static void setNombre(UnmanagedClasseTest* c, int nbr*);
static int getNombre(UnmanagedClasseTest* c);
static void Uctor(UnmanagedClasseTest* c);
static void Udtor(UnmanagedClasseTest* c);
static void UsetNombre(UnmanagedClasseTest* c, int i);
static int UgetNombre(UnmanagedClasseTest* c);

#endif

When I want to compile this unmanaged class I have these errors :/

[C++ Erreur] Unmanaged.h(6): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(7): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(8): E2451 Symbole 'UnmanagedClasseTest' non define

[C++ Erreur] Unmanaged.h(9): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(10): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(11): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(12): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(13): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.cpp(17): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(20): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(23): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(26): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(30): E2034 Impossible de convertir 'UnmanagedClasseTest *' en 'int *'

[C++ Erreur] Unmanaged.cpp(30): E2342 Mauvaise correspondance de type dans le paramètre 'c' ('int *' désiré, 'UnmanagedClasseTest *' obtenu)

[C++ Erreur] Unmanaged.cpp(33): E2034 Impossible de convertir 'UnmanagedClasseTest *' en 'int *'

[C++ Erreur] Unmanaged.cpp(33): E2342 Mauvaise correspondance de type dans le paramètre 'c' ('int *' désiré, 'UnmanagedClasseTest *' obtenu)

[C++ Erreur] Unmanaged.cpp(36): E2268 Appel à une fonction non définie 'setNombre'

[C++ Erreur] Unmanaged.cpp(36): E2231 Le membre UnmanagedClasseTest::nombre ne peut pas être utilisé sans un objet

[C++ Erreur] Unmanaged.cpp(39): E2034 Impossible de convertir 'UnmanagedClasseTest *' en 'int *'

[C++ Erreur] Unmanaged.cpp(39): E2342 Mauvaise correspondance de type dans le paramètre 'c' ('int *' désiré, 'UnmanagedClasseTest *' obtenu)
Munim Munna
  • 17,178
  • 6
  • 29
  • 58
EdelMartin
  • 11
  • 1
  • 2
  • 1
    Question has been asked many time. Visit https://social.msdn.microsoft.com/forums/vstudio/en-US/6215d368-ec60-4712-850d-746c0a078b85/trying-to-call-c-dll-in-c and http://www.codeproject.com/Articles/14180/Using-Unmanaged-C-Libraries-DLLs-in-NET-Applicatio – husnain_sys Feb 05 '15 at 08:14
  • 1
    possible duplicate of [using a class defined in a c++ dll in c# code](http://stackoverflow.com/questions/315051/using-a-class-defined-in-a-c-dll-in-c-sharp-code) – InvisiblePanda Feb 05 '15 at 08:37

2 Answers2

2

I can propose 2 solutions. (1) Export the whole C++ by marking it __declspec(dllexport). All its method will be exported from DLL with some mangled names. Find these names (e.g. by means of Depends utility) and write DllImport wrappers in C# code.

(2) Implement basic COM features in your class and use COM interop. Minimal action set:

a) implement IUnknown and IMarshal methods:

class YourClass: public IMarshal
{
  // override AddRef, Release, QueryInterface and Marshal here
  ...

  int __declspec(stdcall) foo(int x);
}

b) Then ComImport your class in C#:

[ComImport, Guid("5BADB572-FE70-4602-8854-E4B461FC5DAE")] 
class YourClass
{ 
  [PreserveSig] int foo(int x);
}

c) Write a C++ function creating YourClass instances, export it from DLL and write DllImport wrapper for it.

Nikerboker
  • 764
  • 7
  • 14
0

There are several prerequisites to accomplish your task.

  1. You have to knpw where the file resides.
  2. You have to knpw the signature for the method(s) you wish to call.

Suppose that your dll (mycpp.dll) is at location "c:\mycpp.dll" and there is a method named "Sum", which takes two int parameters a and b respectively and returns int. You can use the following code:

public class Program
{
    [DllImport(@"c:\mycpp.dll")]

    private static extern int Sum(int a, int b);

    static void Main(string[] args)
    {
        Console.WriteLine(Sum(3,5));
    }
}

P.S: You can find the original piece of code at : Dynamic Invoke C++ DLL function in C#

user3021830
  • 2,784
  • 2
  • 22
  • 43
  • 1
    I don't know if this answers the question, as it is specifically asked how to deal with a C++ *class* inside the DLL. I think the OP already knows how to invoke the functions, since he wrote that his colleague did this with C code. The important part seems to be the *class* here. Unfortunately, I don't know either if it's possible or how to do it, but I'm genuinely interested in this case as well. There is a related question though that looks like it very much. – InvisiblePanda Feb 05 '15 at 08:35
  • Yes, this is the important point. I have code where functions are invoked and I know how to do this. What I want to do is to use in my C# code the class that is define in the C++ DLL and I don't know if it is possible. I'm still searching :D – EdelMartin Feb 05 '15 at 08:41
  • If you are thinking of using a code like `MyClass.Sum(3, 5)` from C#, I think you can't. Since unmanaged dlls do not have CLR headers, you can not access to class information in such a way. But providing a C interface to you r C++ code might be a good idea as suggested in [here](http://stackoverflow.com/questions/20889482/make-c-class-in-a-native-dll-to-use-in-c-sharp/20890332#20890332) – user3021830 Feb 05 '15 at 08:49