I have a lot of Unmanaged C++ code written in classes &
stored in a DLL which exports theses classes. I would like
to call these classes from new C# Code.
Is there any way to import my Unmanaged C++ classes from
my DLL into a C# Program?
Thanks
Peter Tewkesbury
Assuming you had a C++ class exported from a DLL and functions to
create/destroy it like this:
//<CPPClass>
// This class is exported from the CPPClass.dll
class __declspec(dllexport) CPPClass {
public:
CPPClass();
void SetData(int i);
void DisplayMessage(TCHAR *lpstr);
private:
int m_iData;
};
//Need to have a funtion to call the constructor:
extern "C" __declspec(dllexport) CPPClass* CreateCPPClass() {
return new CPPClass();
}
//Need to have a function to call the destructor too:
extern "C" __declspec(dllexport) void DeleteCPPClass(CPPClass* pClass) {
delete pClass;
}
//</CPPClass>
You could use it in C# like this:
//<CSHARP>
using System;
using System.Runtime.InteropServices;
class CPPClass : IDisposable {
//Variable to hold the C++ class's this pointer
private IntPtr _this = IntPtr.Zero;
public CPPClass(){
//We have to Create an instance of this class through an
exported function
_this = CreateCPPClass();
}
public void DisplayMessage(string test){
//Delegate the call to the C++ member function
CPPClass_DisplayMessage(_this, test);
}
public void SetData(int data){
//Delegate the call to the C++ member function
CPPClass_SetData(_this, data);
}
public void Dispose(){
Dispose(true);
}
protected virtual void Dispose(bool disposing){
if(_this != IntPtr.Zero){
//Call the DLL Export to delete this class
DeleteCPPClass(_this);
_this = IntPtr.Zero;
}
if(disposing){
//No need to call the finalizer since we've now cleaned
//up the unmanaged memory
GC.SuppressFinalize(this);
}
}
//This finalizer is called when Garbage collection occurs, but only if
//the IDisposable.Dispose method wasn't already called.
~CPPClass(){
Dispose(false);
}
//These are the functions exported from the DLL that we call.
[DllImport(@"CPPClass.dll")]
private static extern IntPtr CreateCPPClass();
[DllImport(@"CPPClass.dll")]
private static extern void DeleteCPPClass(IntPtr instance);
[DllImport(@"CPPClass.dll",
EntryPoint="?DisplayMessage@CPPClass@@QAEXPAD@Z", //Use
Depends.exe to get this EntryPoint
CallingConvention=CallingConvention.ThisCall)]
private static extern IntPtr CPPClass_DisplayMessage(IntPtr _this,
string lpstr);
[DllImport(@"CPPClass.dll",
EntryPoint="?SetData@CPPClass@@QAEXH@Z", //Use Depends.exe to
get this EntryPoint
CallingConvention=CallingConvention.ThisCall)]
private static extern IntPtr CPPClass_SetData(IntPtr _this, int data);
}
class RunTest{
[STAThread]
static void Main(string[] args) {
//Create a new instance of the wrapper class
using(CPPClass myClass = new CPPClass()){
myClass.SetData(21);
myClass.DisplayMessage("String from C#");
}
}
}
//</CSHARP>
David Stucki
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.