How do you import a Unmanaged C++ Class into C#

2050 views
Skip to first unread message

Peter Tewkesbury

unread,
May 1, 2003, 4:24:41 AM5/1/03
to
Hi,

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

David Stucki [MS]

unread,
May 1, 2003, 1:32:22 PM5/1/03
to
There's a sample in the .NET Framework SDK named ClassMethods.cs
(%FrameworkSDK%\Samples\Technologies\Interop\PlatformInvoke\Custom\CS\ClassM
ethods.cs) that shows a simple sample of doing this. Here's a slightly
extened sample that I made that completely wraps a C++ class so that C#
clients can use it like any other managed class.

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.

Reply all
Reply to author
Forward
0 new messages