How to dispose/delete managed object from C++/CLI - dll

I'm working on a native C++ project (/clr enabled) that must use a couple of managed, COM visible C# DLLs. Some of the managed objects implement IDisposable and I would like to call Dispose() on them. How can I do that?
The code looks something like this:
HRESULT hr = CoInitialize(NULL);
IManagedClassPtr pIObj(__uuidof(ManagedClass));
//do stuff with pIObj
...
//dispose of pIObj somehow
...
CoUninitialize();

First of all, if you don't have to, just don't use COM.
C++/CLI is designed to give an easy interface between C++ and .Net languages.
If you want to create a .Net object in C++/CLI you just use gcnew with a reference variable.
.Net classes that have a Dispose() method will have it in C++/CLI too. The difference is that if you declare a ref class (.Net reference class) in C++/CLI then the ~destructor turns into a Dispose method.
The !finalizer is what's actually called by the GC.
So anyway, if you create a .Net object with a Dispose() method, you would be able to do this:
MyDisposable^ m = gcnew MyDisposable();
m->Dispose();

Related

Pass objects from referenced managed dll to a C++/CLI wrapper

So, I'm a writing a C++/CLI wrapper and I would like it to interact with objects from a referenced, managed (C#) dll. More specifically, in my C++/CLI project, I would like to have classes like this:
public ref class MyClass
{
public:
void InputPoints(array<Point3d^>^ ptsIn);
};
Where, "Point3d" is an object from the referenced, managed dll - call it "MyGeometryDLL.dll". This compiles without any problems, however when I use the wrapper in a C# project (that also references "MyGeometryDLL.dll") , I can't pass Point3d directly to the wrapper, i.e., intellisense detects:
void MyClass.InputPoints(ValueType[] ptsIn);
How would I pass Point3d directly to the wrapper?
So class Point3d is already defined in a C# DLL, correct? In that case, I think it may be an issue of carats.
If it's declared in C# as public struct Point3d, then it's a value type, not a reference type. That means that whenever you use it in C++/CLI, you don't use the ^, and you don't call gcnew. If that's the case, then you need to change the method declaration to this:
void InputPoints(array<Point3d>^ ptsIn); // No carat on Point3d
The reason that C# sees this as ValueType[] is because Point3d^ is a legal type in C++/CLI, but it doesn't exist in C#. A general ValueType is the closest thing, so that's what C# sees.

Managed client implementing interfaces defined in managed COM object

I'd like to have a managed com object that exposes methods which accept as arguments objects implementing given interfaces. Something like this
[ComVisible(true)]
[Guid(".....")]
class SomeClass {
public void SomeMethod(ISomeInterface arg)
.....
Apparently ISomeInterface should also be declared ComVisible.
Now I want to consume that COM object in a managed client and call SomeMethod there. The problem is I need to instantiate an object that implements ISomeInterface. If that was a native COM object I'd get an interop assembly generated automatically and that won't be a problem. One cannot generate an interop assembly for managed COM object though.
I see that .NET 4.0 introduces the type equivalence concept. It looks like I could generate an interop manually using the ComImport attribute. But that looks like a pretty nasty job. I guess I could also use the TypeIdentifierAttribute but the documentation on that is vague and it says it's mostly intended for use by compilers.
So are there any other ways to do that?

Type of Class in C++/CLI

I am working on C++/CLI Wrapper for C Static Library.Static Library has 10 function in it.
THis C++/CLI Wrapper will Expose 10 API to C# Application.The Wrapper Will be in the Form of dll.
The Wrapper Will be Used in C# Application.
Now I am trying to add a class in C++/CLi application which will expose function to C# application I am getting Many Option like
C++ Class
CLR Class
a. Component Class
b.Installer Class
c. Windows Form
d. Installer Class
I am bit confused which I need to select out of it as I am new bee in C++/CLI
You need a
CLR Class - Component
since it can be consumed by .NET clients.
CLR class is declared as follows
ref class Wrapper {....}
However in your scenario you could also write a dynamic library and pinvoke the methods from .NET client.
Not sure if your question has been entirely answered, but a Component class creates a class that implements an IComponent interface for remoting/ inter process communication purposes. Didn't seem like what you were looking for.
I think what you were looking for i just a "template" to create a managed class?
In that case all you need to do is select C++ in the wizard and make sure the "Managed" check box on the right hand side is selected.

How to manage .Net's RCW COM object creation paramets (namely requested interface)?

I'm using an external native COM component in my C# .NET application.
This COM DLL doesn't have a type library, so I had to write the interop code myself, and having include/idl files I did it like TlbImp does.
But the worst thing is that the object creation fails with:
Creating an instance of the COM component with CLSID {40700425-0080-11D2-851F-00C04FC21759} from the IClassFactory failed due to the following error: 80040111
The class is finally created if I use the native CoCreateInstance and specify class_id and one of the implemented interface IIDs.
As it turned out the problem lies in that the COM object's IClassFactory::CreateInstance doesn't support IID_IUnknown passed as the riid parameter, and therefore returns CLASS_E_CLASSNOTAVAILABLE (I identified it with disassembler and debugger). The component is MS SQL VDI.
Is there any way to force the .NET RCW to pass a different interface ID into the CreateInstance method rather than IID_IUnknown?
I searched the net a lot, but didn't find a solution for this.
As a workaround I'm using C++/CLI now to create the object, requesting the proper interface instead of IID_IUnknown for this purpose now; but I would like to have code in C#, because C++/CLI requires me to build a different DLL for each platform.
Thanks
I repro. Brr, painful. You could pinvoke CoCreateInstance:
[return: MarshalAs(UnmanagedType.Interface)]
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
public static extern object CoCreateInstance(ref Guid clsid,
[MarshalAs(UnmanagedType.Interface)] object punkOuter, int context, ref Guid iid);

C++/CLI umanaged pointer in constructor

I want to make a C++/CLI wrapper of some C++ class.
The problem is that I want the ref class to be initiated with a reference of the c++ object:
A (A& a);
This works fine as long as it is in the same aseembly and used in the same project.
But when I try to reference that project from a different project, and initiate a ref-class with a reference to an object from there, it won't recognize the types properly, and doesn't recognize the correct constructor.
Any ideas of how to solve this ?
I don't think you will be able to use a reference to the C++ object in this instance, but you can pass a pointer to the C++ object across assembly boundaries by storing it in an IntPtr and then retrieving it using static_cast.
class nativeA; // Pre declaration
A (IntPtr a)
{
nativeA * nativePtr = static_cast<nativeA*>(a.ToPointer());
// Do something with nativeA
}