Working with managed COM object from unmanaged code - c#

Let's say I have a well-known interface IWellKnownInterface, which is known to be COM-visible and registered.
I also have a managed (C#, to be exact) implementation of this object:
public class MyWellKnownClass : IWellKnownInterface { ... }
And, finally, I have an extern method, which accepts the object of this interface:
[Whatever]
private static extern void ExternMethod(IWellKnownInterface veryWellKnown);
Question 1:
I would like to know what happens beneath the following code from the CLR point of view:
IWellKnownInterface a = new MyWellKnownClass();
ExternMethod(a);
I'm aware that if we're talking about calling unmanaged COM object from managed code, it's all about constructing an appropriate Runtime Callable Wrapper and delegating the calls via it with appropriate argument conversion. However, I could not find any information about the situation when we've got a managed COM object and it's being used in unmanaged code.
Question 2:
How does the dynamic type affect the behavior of the CLR in the same situation? Would it somehow change the internal managed-to-unmanaged interop logic? Maybe add some additional wrappers for the MyWellKnownClass instance?
dynamic a = new MyWellKnownClass();
ExternMethod(a);

Question 1:
The first line does nothing but create an object. There is nothing special or different that is happening from any other CLR object. This is because nothing has been actually marshaled to unmanaged code.
However, on the second line, a COM callable wrapper is created and marshaled across to unmanaged code. Think of this as the reverse of the runtime callable wrapper, handling the calls from unmanaged code back to your managed implementation of a COM interface.
Question 2:
The dynamic type doesn't impact the call at all. In this particular case, you're passing the managed reference to unmanaged code. The type of a is MyWellKnownClass, the only thing that dynamic does is change how calls to that are resolved in managed code. When the COM callable wrapper is created, it has a hard reference to the instance of MyWellKnownClass, not to the dynamic variable; the only thing that changes is that when ExternMethod is called, the resolution of the method that is called occurs at runtime and not at compile-time.

Related

How can I use types from a wrapped resource outside of the wrapper?

I'm trying to wrap a COM API so that others can use my wrapper without knowing anything about the wrapped API. However, I've hit a problem trying to use some of the items from the COM API.
Let's say the COM API has a method that returns an object defined within the API.
IComChildObject IComObject.GetChildObject()
If I have a reference to the dll that defines the COM API, I can easily use this as follows...
IComChildObject childObject = myComObjectInstance.GetChildObject();
The problem I have, is that I need to be able to work with the IComChildObject through the wrapper class, without referencing the COM API dll.
I tried to create an interface in my wrapper, that would accomplish this. So inside my wrapper project, I have an interface like this.
public interface ILocalChildObject : IComChildObject{}
Then I added a property to my wrapper, that I thought would allow my external code to use the IComChildObject.
public class ComWrapper
{
IComObject comObject;
public ILocalChildObject ComChildObject { get { return comObject.GetChildObject() as ILocalChildObject;}}
}
When I run the following code from my external code, the ChildObject is null
ILocalChildObject ChildObject = myComWrapper.ComChildObject;
I'm obviously doing something wrong, but I'm in over my head on this and don't even know what to search Google for.
Maybe it's not clear what I'm trying to do, or maybe I'm trying to do something strange here. I want to create a wrapper class library in such a way, that the code that uses it doesn't have to know anything about the wrapped library. I've done okay so far, up until the point where I need to use objects from the wrapped library in the external code. I could easily resolve this by referencing the wrapped library in my external project, but I'd like to avoid doing that.
Basically, I just need a way to use the IComChildObject in my external code, without adding a reference to the COM API dll.
Any help would be greatly appreciated,
If your API is based on IDispatch you could use the dynamic keyword, something like this:
dynamic childObject = GetChildObjectSomehow();
childObject.CallAnyMethod() // compile will always succeed, will be resolved at runtime (and failed if there's like a typo error)
Note dynamic is not available on .NET core for COM objects yet.
If it's not (if it's based on IUnknown), then you'll have to declare this interface either in an external dll or .tlb, or directly in your C# code, so it can be called by the .NET runtime. You don't have to use the original .dll, you can redefine the interface by yourself if needed (maybe a simplfied version). But the runtime has to know the binary layout to be able to call it.
Another way to handle this, as Hans Passant points out, is to wrap the COM API object in a class. Then you can access the properties within the object through the new object. The only downside to this approach is there's a lot of typing, as you have to recreate any properties or methods that you want to access in the COM API object.
In the wrapper project, you'll create a class that will contain the object returned from the API. This class will also have properties and methods, that allow a user to manipulate the API object through the class.
public class LocalChildObject
{
internal IComChildObject ComChildObject;
public string ChildObjectProperty { get { reutrn ComChildObject.ChildObjectProperty; } set { ComChildObject.ChildObjectProperty = value ;}}
public LocalChildObject(IComChildObject ComChildObject)
{
this.ComChildObject = ComChildObject;
}
}
In this example, ComChildObject is the object returned from the API. Then there's a property in the class ChildObjectProperty, which allows you to get or set the ChildObjectProperty of the ComChildObject.
Then in my main wrapper class, I can have a property that returns this new object (which contains the API COM object).
public class Wrapper
{
public LocalChildObject GetLocalChildObject { get { return new LocalChildObject(ComObject.GetChildComObject());}}
}
Then in the external code I can make changes to the object through the new wrapper object
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
This method requires recreating all the properties and methods that you want to expose through the wrapper, however, it does allow the user using the wrapper to use IntelliSense.

Enforce one common instance of static variables to all threads when running in the context of appDomain

Environment:
.NET Program that contains multiple dlls/assemblies of managed + native code.
The first action performed by the program is to create an instance of a class (say classA) that is inherited from MarshalByRefObject, within a namespace (say namespaceA).
Actions done as part of classA constructor:
Allocates new class (say classB). classB contains static variables.
Create threads. The actual creation of the threads is done in the context of the native code by calling the ‘WinBase’ ‘CreateThread’ function.
Problem:
When defining an instance of classA within the context of appDomain, classB static variables are not common to all threads.
The code used to load the programs dll and create instance of classA within appDomain:
System.AppDomain app_domain = System.AppDomain.CreateDomain("app domain");
object winfw_host = app_domain.CreateInstanceFromAndUnwrap(#"C:\...\dll_name.dll", "namespaceA.classA");
Note:
When defining an instance of classA not in the context of appDomain, classB static variables are common to all threads.
Question:
I would have expected same behavior (AppDomain and non-AppDomain context), what is the reason for the difference?
Is it possible to enforce one common instance of static variables to all threads when running in the context of appDomain?
The scope of a static variable is exactly the containing AppDomain. In order to recover this limitation, I would recommend to use some tricky way.
You select an AppDomain (let's say A).
AppDomain class exposes the following non-static methods.
GetData(String)
SetData(String, Object)
Try to store the value shared by all AppDomain by A.SetData("your Key", value), and retrieve value by A.GetData("your key")
You will need to also think of thread safe access when accessing the AppDomain A.
Microsoft approved that it is an expected behaviour that when creating multile threads in appDomian context, static variable are not to be common for all thread (unlike non-appDomain, one static variable for all threads) and it’s how C++/CLI was implemented.
To achieve this kind of requirement it is suggestion is to create a delegate type to wrap managed method call so it could be passed to native code into the native threads, because delegates preserve that AppDomain information across native threads. Basically, you create the managed delegate, allocate a GCHandle for the delegate to reference it in your native C++ code, then call Marshal::GetFunctionPointerForDelegate on the GCHandle to get the native function pointer to the delegate. The last part requires a static cast of the IntPtr to your native function type. You can then pass that native function pointer you obtain across threads.

C# dynamic & COM objects

from here
A very big advantage of dynamic types comes when you start to think
about C#’s relationship with external and non-native objects – COM
objects in particular. In this case a dynamic type is resolved using
the COM IDispatch interface and this in turn means that you can use
COM objects “raw”, i.e. without a Primary Interop Assembly (PIA). As
many COM objects make extensive use of the variant type, which can
store any of a number of standard data types, being able to use
dynamic types in place of variants is a big simplification.
I already know how dynamic is used in C# , However - I want to know how it is done.(generally with COM)
looking at Office COM object model example :
(Excel.Range)excel.Cells[1,1]).Value= "some string"
The cast has to be included because the PIA uses object types to represent variants
Now (2010 ...), with dynamic it can be done with :
excel.Cells[1,1].Value= "some string"
But
An object can provide its binding semantics by implementing DynamicObject
such as :
public class MyClass: DynamicObject
{
public override bool TryInvokeMember ( InvokeMemberBinder binder, object[] args, out object result)
{
...
}
}
So my question :
Did MS [changed] or [added code] or [now-inherit-DynamicObject] the COM objects in order to allow excel.Cells[1,1].Value= "some string" to work ?
Did they re-build this whole mechanism ?
No, the secret sauce is COM here. This is done with only 2 interfaces and 5 methods. The first one is IUnknown, an interface implemented by all COM objects. It has 3 methods:
AddRef(), increments the reference count on a COM object. This is a memory management function, as long as the count is non-zero the object stays alive. Storing a pointer to a COM object requires calling IUnknown.AddRef().
Release(), decrements the reference count. The opposite of AddRef and must be called when an interface pointer is no longer used. The COM object is released when the count reaches zero. This function is the core reason behind the rather infamous use of Marshal.ReleaseComObject() in .NET code that uses Office. It normally gets called by the finalizer of a COM wrapper.
QueryInterface(), asks the COM object to return a pointer to another interface. In the scope of this question, that's how C# gets the IDispatch interface pointer.
The IDispatch interface is the one that implements dynamic binding, the rough equivalent to DynamicObject. It has 4 methods, 2 of which are important in this context:
GetIDsOfNames(), converts a name to a number, a dispid. This is how an identifier in a C# program can be matched to a method or property name on the COM object.
Invoke(), calls the COM method of property getter/setter, using the dispid
That's the big picture, use the MSDN Library if you want to know more about these interfaces.
The DLR (which is what the dynamic keyword offers interface to) uses "binders" to interface with the dynamic object proper (there is a C# binder, VB binder, COM binder etc.). The COM binder is a separate component that uses the "traditional" COM interop, which is not replaced and can still be used without dynamic. It was enhanced for .NET 4.0, but not just for dynamic.
You can use dynamic with any type. You need to derive from DynamicObject only when you want your classes to provide a dynamic interface.
The following line works, without requiring DateTime to inherit from DynamicObject:
dynamic myDate=DateTime.Now;
EDIT
As to how COM+ supports dynamic binding - it always did. In fact, the documentation explains exactly how this is done.
COM always supported its own kind of dynamic binding through the IDispatch interface which works roughly like DynamicObject. IDispatch allows an object to respond to queries for specific interfaces and the methods it supports.
dynamic can use the IDispatch interface for raw COM objects, where you don't have a type library or a proxy. In other cases, dynamic will call the proxy methods without going through the IDispatch interface.
Dynamic binding in COM introduces a performance hit, due to the multiple calls needed to extracta a specific interface and invoke its methods. In the VB6 days people tried to minimize or eliminate the use of dynamic binding by using type libraries. This is sound advice for .NET as well.

Cache to map IntPtr handles to C# class instances in pinvoke callbacks

I'm writing a C# wrapper around a native dll that uses opaque pointers to identify resources. A typical example would be something like
typedef struct session session;
typedef struct track track;
void* sessionCreate(int arg, session** sess);
void sessionRelease(session** sess);
track* sessionGetTrack(session* sess, int index);
void trackAddRef(track* trk);
void trackRelease(track* trk);
int trackGetLength(track* trk);
In my wrapper, I've created C# classes corresponding to the different opaque types, with member functions corresponding to the various functions using the different opaque types.
This is fine. There are also callbacks from the dll, for example
void(* track_changed )(track *trk, bool changedExternally);
In order to map from the static delegate that handles the callback to the object that corresponds to the handle supplied, I'm using a static dictionary of WeakReferences (IntPtr/SafeHandle as key, object reference as aata) in each of my classes.
So what is the right way to approach removing entries from the static dictionary? I'm writing library code and cannot rely on my clients to Dispose my objects. Should the I put the code in the finalizer?
Or is there a better way to manage the correspondence between the static callbacks and my object instances?
Your clients really should (indeed I would prefer to say must) dispose of your objects since they are IDisposable, just like they do with other BCL classes.
In any case a bog-standard implementation of the dispose/finalize pattern should cover all bases. There is more related discussion here.

C# object not destroyed when using COM/ATL interface in C++

Lately I was doing a little project that involved a DLL module (that was created with C#) and that I needed to use in my application (that was written in unmanaged C++) For this to work I was using ATL/COM.
I noticed that even though I'm using a _com_ptr_t in my C++ application for handling my core COM interface, C# object's destructor is called only when my application is closed.
Let me give you some source to make things a bit more clearer:
Some of my C# code:
[ComVisible(true)]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface ITestCOM
{
[DispId(1)]
void Connect([In, MarshalAs(UnmanagedType.U2)] ushort value);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ITestCOMEvents))]
public partial class TestCOM : ITestCOM
{
...
~TestCOM()
{
MessageBox.Show("DESTRUCTOR");
}
...
public void Connect(ushort value)
{
...
}
}
I'm creating the .tlb file using something like this:
"RegAsm.exe TestCOM.dll /tlb:Test.tlb /codebase"
In my C++ header I have:
#import "C:\...\mscorlib.tlb"
#import "......\TestCOM.tlb" named_guids exclude("ISupportErrorInfo")
#include <afxdisp.h>
#include <atlcom.h>
class Unit : public ::IDispEventSimpleImpl<0, Unit, &__uuidof(TestCOM::ITestCOMEvents)>
{
public:
BEGIN_SINK_MAP(Unit)
SINK_ENTRY_INFO(0, __uuidof(TestCOM::ITestCOMEvents), 0x1, OnEventCallback, &OnEventCallbackDef)
END_SINK_MAP()
...
private
TestCOM::ITestCOMPtr mTestCOM;
// NOTE: This would be the same as "_com_ptr_t<_com_IIID<TestCOM::ITestCOM, &__uuidof(TestCOM::ITestCOM)> > mTestCOM;"
}
And my C++ source file I create my "mTestCOM" like this:
mTestCOM.CreateInstance(TestCOM::CLSID_TestCOM)
And basically that's it.. I can use any of my C# "TestCOM" object's functions like this:
mTestCOM->Connect(7);
The question is:
Why my C# TestCOM object's destructor is called only when my application is closed, and not when my C++ "Unit" object is destroyed?
Though I'm not familiar with C# and COM integration, I do know that destructors in C# work very differently to destructors in C++. A C# object is memory-managed and garbage-collected. This means that at some point after the object stops being referenced by the application it belongs to and becomes 'unreachable', the garbage collector will destroy it.
So the first important thing is that the delay between an object being abandoned and the garbage collector destroying it is nondeterministic... it will happen "at some point in the future", which may well be at the point the application terminates.
Secondly, the garbage collector is not always running. There is the concept of "memory pressure", when your application is allocating large chunks of memory and the free memory available to it is running out... at that point, the garbage collector will fire to get rid of old, unreachable objects. If your application does not allocate lots of memory it will not suffer from any memory pressure and the garbage collector will not need to run.
If you want to deterministically clean up some of a managed object's resources, you will need to use something like the IDisposable interface and call the Dispose method explicitly.
This is entirely normal and a side-effect of the garbage collector. Which only collects garbage, and runs the finalizer, when a managed app allocates enough memory to fill up a generation and trigger a collection. If you don't allocate enough then this won't happen until the app terminates.
This should not be a problem, make sure that you don't use the finalizer to do anything other than release unmanaged resources that were not disposed. Writing a finalizer is the wrong thing to do in 99.9% of all cases, finalizers are implementation details of .NET framework classes. Like the SafeHandle classes. There is otherwise no way to let deterministic destruction in the client app produce deterministic disposal in the managed code. If you do need to dispose members then you'll need to expose a method that the client code can call.

Categories

Resources