Interoping classes

  • Thread starter Thread starter Udi
  • Start date Start date
U

Udi

Hi,
How do I work with a C++ class that is given through a dll?
can someone please give me a short C# example of how to work with the
following code?
Thanks!


class MyClass
{
private:
char * m_data;
public:
MyClass(){...}
int DoSomthing(char * buf){...}
}
 
Udi said:
Hi,
How do I work with a C++ class that is given through a dll?
can someone please give me a short C# example of how to work with the
following code?
Thanks!


class MyClass
{
private:
char * m_data;
public:
MyClass(){...}
int DoSomthing(char * buf){...}
}

If you mean to call a method in a C++ DLL:

[DllImport("KERNEL32.DLL", EntryPoint="MoveFileW", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool MoveFile(String src, String dst);

The above is from the VS.NET docs. Look at DLLImportAttribute class for
more information. Make sure you have a reference to the DLL in your project.

Brett
 
Udi said:
Hi,
How do I work with a C++ class that is given through a dll?
can someone please give me a short C# example of how to work with the
following code?
Thanks!


class MyClass
{
private:
char * m_data;
public:
MyClass(){...}
int DoSomthing(char * buf){...}
}

You can't directly access unmanaged C++ code from C# and you can't PInvoke
native C++ class member functions.
So what you should do is author a managed wrapper class using VS2003 ME C++
(or the upcoming C++/CLI ) that serves as a thunk.

Here's a sample...

#include "nativeheader.h"
#include <vcclr.h> // needed for PtrToStringChars
// Wrapper class
public __gc class MyClassWrapper
{
private:
MyClass* mc;
public:
MyClassWrapper() : ac( new MyClass()){}
int DoSomthing(System::String buf)
{
// convert String to char*
__const_Char_ptr wch = PtrToStringChars( buf );
return mc->DoSomthing(buf);
}
~MyClassWrapper() {
delete mc;
}
};


in C#, add a reference to the wrapper DLL and use the class like any other
managed class:

...
MyClassWrapper mcw = new MyClassWrapper();
mcw.DoSomthing(...);



You might find much more info on the VC++ MSDN site
http://msdn.microsoft.com/visualc/

Willy.
 
Brett Romero said:
Udi said:
Hi,
How do I work with a C++ class that is given through a dll?
can someone please give me a short C# example of how to work with the
following code?
Thanks!


class MyClass
{
private:
char * m_data;
public:
MyClass(){...}
int DoSomthing(char * buf){...}
}

If you mean to call a method in a C++ DLL:

[DllImport("KERNEL32.DLL", EntryPoint="MoveFileW", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool MoveFile(String src, String dst);

The above is from the VS.NET docs. Look at DLLImportAttribute class for
more information. Make sure you have a reference to the DLL in your
project.

Brett

No, this won't work. The class is a native C++ class, you can't (and you
shouldn't) set references to native code DLL's and you can't call member
functions in native classes fom C#.

Willu.
 
Thanks Willy!
I really appreciate it!
What if I need an out string parameter?
I mean PtrToStringChars returns a const char, what is the right way to
initialize it inside
MyClass and return it back from the wrapper?

int DoSomthing(out System::String * buf)
{
// convert String to char*
__const_Char_ptr wch = PtrToStringChars( buf );
return mc->DoSomthing( wch ); --> need it out here!
}
 
Udi said:
Thanks Willy!
I really appreciate it!
What if I need an out string parameter?
I mean PtrToStringChars returns a const char, what is the right way to
initialize it inside
MyClass and return it back from the wrapper?

int DoSomthing(out System::String * buf)
{
// convert String to char*
__const_Char_ptr wch = PtrToStringChars( buf );
return mc->DoSomthing( wch ); --> need it out here!
}

Difficult to answer, it depends who allocated the buffer holding the string,
what allocator has been used and what string type it is (ansi, unicode).
Following sample that assumes the callee (native code) allocates and
returns an ansi string.

// managed wrapper
int SomeWrapper::RetString(System::String** buffer)
{
// allocate native memory to hold the pointer to the char* returned by
callee
System::IntPtr pointerTobufPointer =
Marshal::AllocHGlobal(sizeof(void*));
int ret = ac->RetString(static_cast<char**>(pointerTobufPointer
..ToPointer()));
if (buf != 0)
{
*buffer =
Marshal::PtrToStringAnsi(Marshal::ReadIntPtr(pointerTobufPointer ));
}
return ret;
}

// native C++
int SomeClass::RetString(char** buffer)
{
s = "Hello Ansi world";
*buffer = const_cast<char*>(s.c_str());
return s.length();
}

...
std::string s;

// In C#
SomeWrapper sw = new SomeWrapper();
int ret = sw.RetString(ref s);
...

Note that - I suggets you read all possible documents and white papers found
on http://msdn.microsoft.com/visualc/, and as your questions relate to C++
you might better post to the vc NG microsoft.public.dotnet.languages.vc

Willy.
 
Back
Top