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

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.

Related

How do compilers compile virtual/overridden methods

I am developing a compiler for an object oriented language targeted on a virtual machine I wrote that I am using as a cross platform abstraction layer. I am sort of confused about how inherited methods works. Lets say I had the following lines of C# code.
class myObject : Object {
public int aField;
public override string ToString() {
return "Dis be mah object";
}
public void regularMethod() { }
}
Object test = new myObject();
Console.WriteLine(test.ToString());
Now this would output 'Dis be mah object'. If I called regularMethod however the compiled code would in reality do something like this:
struct myObject {
public int aField;
}
public static void regularMethod(ref myObject thisObject)
{
}
How would the inherited method ToString be handled after compilation? The compiler could not do what I did above with regularMethod, because if it did then 'Dis be mah object' would only be returned when creating myObject types and not plain Object types. My guess is that the struct myObject would contain a function pointer/delegate that would get assigned when a new instance is created.
If you are dealing with static overloading, it is really simple: you bind to the correct implementation when processing the code.
But, if you are working with dynamic overloading, you must decide things at runtime. For this you need to use dynamic dispatch, using the real object type. This is the same thign that is done with method overriding.
Dynamic dispatching is not the same as late binding. Here, you are chosing an implementation and not a name for your operation (despite the fact that this binding will occur at compile time, the implementation will only occur at runtime).
Staticly, you would only bind to implementation of the declared type of the object. It is done at compile time.
The are some mechanisms you could use to achieve the dynamic dispathing, it will dictate your language paradigm.
Is your language typed? Weakly typed?
C++, for instance, offers the two types of dispatch I mentioned. For the dynamic one (which I believe is the one you are interested), it uses a virtual table to do the mapping for one class. Each instance of that class will point have a pointer to that vtable.
Implementing
The vtable (one for all objects of same class) will have the addresses of all dynamicly bound methods. One of those addresses will be fetched from this table when a call is made. Type-compatible objects have tables with addresses with the same offset for the methods of all compatible classes.
Hope I've helped.

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?

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

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();

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
}