Reputation: 11
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)
Upvotes: 0
Views: 8914
Reputation: 843
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.
Upvotes: 2
Reputation: 2924
There are several prerequisites to accomplish your task.
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#
Upvotes: 0