Re: Wanting a better method of interop.
Peter Ritchie <[email protected]> Fri, 20 Oct 2006 13:19:45 -0400
| Newsgroups | gmane.comp.windows.devel.dotnet.cx |
|---|---|
| Message-ID | <LISTSERV%[email protected]> |
I've done some fairly complex interop with legacy native C/C++ code and
managed code in VC2005.
In my case I had the source for a C/C++ library that I needed to make
available to managed code. What I did was create a managed assembly that
wrapped the API presented in the C/C++ library (actually a subset, I
didn't need it all). I used C++ interop (the VS2005 equivalent of "It
just works" (IJW)) AKA Implicit PInvoke. Basically you can create a C++
CLR/Class Library project and add C/C++ files to that project to your
heart's content. The compiler is smart enough to know that is native code
(from the lack of "ref" keyword, etc.) and compiles as such and tucks it
away in the assembly. You can then write managed code that accesses that
legacy code in the very same way you would with native code. The compiler
deals with generation of ALL The interop for you (hence the moniker "It
just works").
For example, if you hand a legacy C++ header (MyNativeClass.h) as follows
(aircode):
class MyNativeClass {
private:
int m_value;
public:
MyNativeClass() : m_value(1) {}
void SetValue(const int value) { m_value = value;}
int GetValue() const {return m_value;}
};
you could create managed code to access that native code (aircode) similar
to:
public ref class MyManagedClass abstract sealed
{
public:
static int DoSomething()
{
MyNativeClass myNativeClass;
return myNativeClass.GetValue();
}
}
You'll see from the above there's no explicit PInvoke stuff like
DllImportAttribute and it's marshalling abilities all the PInvoke and
marshalling (except for pinning) is handled for you.
C++/CLI (and "managed C++ in VC2003) was specifically designed to ease the
transition of legacy C/C++ code in this way. As you convert native C/C++
to C++/CLI the interface presented to the managed world need not change--
it's an implementation detail.
The above example is really simple. If you're getting into passing
managed memory into native C/C++ you'll have to get into pinning the
memory (you're allowed to pass a pointer to managed memory to native code
without pinning it, which is never safe). For example (again, aircode) if
you have a managed method that accepts data and you want to pass it to
native code (like MyNativeClass::ProcessData) you could do the following:
void ProcessData(array<array<Byte>^>^ data)
{
{
pin_ptr<Byte> pByte = &data[0][0];
void * pVoid = pByte;
MyNativeClass::ProcessData(pVoid);
}
}
I try to make a point of scoping the code between before the pin_ptr and
after the last use of the native pointer to ensure the memory is unpinned
as soon as possible.
Again, the above is all VC2005, not 2003. There's lots of new features in
C++/CLI (VC2005) that make interop much nicer.
If you get into mixing your managed and unmanaged code into the same file
you may need to get into using "#pragma managed" or "#pragma unmanaged"
when the compiler can't figure it out for itself. I try to keep the
managed and unmanaged code in separate source files for my own sanity.
I found the following reference useful when implementing my C/C++ interop
stuff:
http://msdn2.microsoft.com/en-us/library/2x8kf7zx.aspx
===================================
This list is hosted by DevelopMentorĀ® http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com