Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / July 2006

Tip: Looking for answers? Try searching our database.

Passing COM object from managed to unmaged code in .Net

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
C# Dev - 14 Jul 2006 09:28 GMT
Greetings,

Is it possible to pass a COM object from unmanaged C++ to C# (and possibly
back?)

Say create the object in C++, pass it to - and then invoke it in - managed
.Net?

Is yes, what is required in terms of
- C++ and C# interface declaration
- memory management

For this to succeed?

Any sample would be most helpful.

Cheers
quension@gmail.com - 21 Jul 2006 01:58 GMT
> Is it possible to pass a COM object from unmanaged C++ to C# (and possibly
> back?)

Yes.

> Is yes, what is required in terms of
> - C++ and C# interface declaration

Basically, the same thing you did in your previous post.

> - memory management

Standard COM rules.  On the unmanaged side, if you're transferring
ownership to the managed side, nothing special.  If you're giving it
its own reference, AddRef the object first.  .NET handles refcounting
on the managed side, GC issues etc.

> Any sample would be most helpful.

This is what I used as a test case for your previous thread.

Unmanaged C++ ----------------------------------------
[uuid("a52e9a6f-d286-451d-aaa3-e43b5c182032")]
interface ITest : IUnknown
{
   HRESULT __stdcall GetVal(int *i);
   HRESULT __stdcall GetReason(VARIANT *pReason);
};

class TestObject : public ITest
{
   long m_refCount;

public:
   TestObject();
   virtual HRESULT __stdcall QueryInterface(REFIID riid, void **ppv);
   virtual ULONG __stdcall AddRef();
   virtual ULONG __stdcall Release();
   virtual HRESULT __stdcall GetVal(int *i);
   virtual HRESULT __stdcall GetReason(VARIANT *pReason);
};

TestObject::TestObject()
{
   m_refCount = 1;
}

HRESULT __stdcall TestObject::QueryInterface(REFIID riid, void **ppv)
{
   *ppv = NULL;

   if (IsEqualGUID(riid, __uuidof(IUnknown)))
       *ppv = static_cast<IUnknown *>(this);
   else if (IsEqualGUID(riid, __uuidof(ITestBase)))
       *ppv = static_cast<ITestBase *>(this);
   else if (IsEqualGUID(riid, __uuidof(ITest)))
       *ppv = static_cast<ITest *>(this);
   else
       return E_NOINTERFACE;

   this->AddRef();
   return S_OK;
}

ULONG __stdcall TestObject::AddRef()
{
   return InterlockedIncrement(&m_refCount);
}

ULONG __stdcall TestObject::Release()
{
   long result = InterlockedDecrement(&m_refCount);
   if (result == 0)
       delete this;
   return result;
}

HRESULT __stdcall TestObject::GetVal(int *i)
{
   *i = 42;
   return S_OK;
}

HRESULT __stdcall TestObject::GetReason(VARIANT *pReason)
{
   pReason->vt = VT_BSTR;
   pReason->bstrVal = SysAllocString(L"test reason string");
   return S_OK;
}

extern "C"
ITest * __stdcall CreateTestObject()
{
   TestObject *obj = new TestObject();
   return static_cast<ITest *>(obj);
}
------------------------------------------------------

If you haven't seen the interface and [uuid]/__uuidof() stuff before,
it's equivalent to:

   struct ITest : public IUnknown
   {
       virtual HRESULT __stdcall GetVal(int *i) = 0;
       virtual HRESULT __stdcall GetReason(VARIANT *pReason) = 0;
   };
   const IID IID_ITest = { ... }
   if IsEqualGUID(riid, &IID_ITest) ...

Just syntactic sugar.

Managed C# -------------------------------------------
using System;
using System.Runtime.InteropServices;

[Guid("a52e9a6f-d286-451d-aaa3-e43b5c182032")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ITest
{
   int GetVal();
   [PreserveSig] int GetReason(out object reason);
}

class Program
{
   [DllImport("VariantTest")]
   static extern ITest CreateTestObject();

   static void Main()
   {
       ITest test;
       object obj;

       Console.Write("trying CreateTestObject... ");
       test = CreateTestObject();
       Console.WriteLine("succeeded.");
       Console.Write("trying ITest::GetVal... ");
       Console.WriteLine(test.GetVal());
       Console.Write("trying ITest::GetReason... ");
       test.GetReason(out obj);
       Console.WriteLine(obj);
       Console.WriteLine("done");
   }
}
------------------------------------------------------

A lot of people recommend Adam Nathan's book, ".NET and COM: The
Complete Interoperability Guide".  I'm too cheap to buy books, so I've
never read it, although the code samples are available online:
http://www.samspublishing.com/bookstore/product.asp?isbn=067232170X
(download section at the bottom)

Apress has a book freely available in PDF format, "COM and .NET
Interoperability" by Andrew Troelsen: http://www.apress.com/free/

Hope this helps.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.