The API documents describe the method as such:
boolean MethodName(VARIANT* par)
The parameter is a ref type which returns an error code.
How do I call this method using c# 4.0's new features?
Just use the old way, there's nothing in 4.0 that makes this method any easier to use. Add a reference to the COM type library, usually the DLL itself, and you should get a class with the method bool MethodName(ref object). What you are supposed to do with the object is completely unclear from your question. Check the API manual, get help from the component vendor.
Related
TDLR
After researching and testing this problem more (see the update below), I reached this answer:
What I need is to actually pass an object by reference to a DLL created with Matlab using the type-safe API, but this does not seem to be possible. Correct?
I suspect that this is the direct result of them using WCF to facilitate interprocess behind the scenes as mentioned here. The fact that it is a DLL (which essentially handles the communication) confused me very much.
So is there a quick way to achieve this (e.g. COM objects come to mind, but I have not worked with them before)?
/TDLR
I am trying to figure out how to pass a .Net object to a Matlab method and then call a method on that object. In my Matlab Code I have something like this:
DOTNET_object = DOTNET_classFactory.GetStage();
CallDOTNET_class_method_DoSomething(DOTNET_object);
Where DOTNET_classFactory and DOTNET_object are both instances of .Net classes and CallDOTNET_class_method_DoSomething would be a Matlab function defined like this:
function CallDOTNET_class_method_DoSomething(DOTNET_object)
DOTNET_object.DoSomething();
end
I now need to perform the same two lines above in from within C#, after creating a DLL with the function CallDOTNET_class_method_DoSomething. However I am unable to figure out how to pass DOTNET_object to my function in the C# code. Here is what I have:
Class1 = new Class1();
Class1.CallDOTNET_class_method_DoSomething((MWArray) DOTNET_object);
I have found this answer , but I am not sure if this is the correct way to go. Would I have to package all the .Net objects (I will need to pass a total of 3 objects) I want to pass to my Matlab function inside an object-array and that unpack the within or is there a more elegant way, where I can pass the three objects separately and explicitely?
Update:
As explained here here I have now tried using the type-safe API in Matlab and by creating an interface to define the arguments of function CallDOTNET_class_method_DoSomething(DOTNET_object). I have been able to compile it in Visual Studio. Unfortunately, when I run the it I get the following exception:
Result StackTrace:
at MathWorks.MATLAB.NET.Arrays.MWArray.ConvertObjectToMWArray(Object objIn)
at MathWorks.MATLAB.NET.Utility.MWMCR.UnpackArgArray(Object[] argArray, Object[] varArgArray)
at MathWorks.MATLAB.NET.Utility.MWMCR.EvaluateFunctionForTypeSafeCall(String functionName, Int32 numArgsOut, Object[]& argsOut, Object[] argsIn, Object[] varArgsIn)
...
... removed, because it is confidential
...
Result Message: System.IO.InvalidDataException : Input data type unsupported by MATLAB .NET Assembly
From the message I deduce, that my endeavor is in vain and that you cannot pass anything other than primitive/value types (by that I mean, int, double, bool, etc.) to a Matlab DLL as written here here?
Result Message: System.IO.InvalidDataException : Input data type unsupported by MATLAB .NET Assembly
Am I correct in that assumption or is there any workaround?! In other words/another aspect: What I need is to actually pass an object by reference to the DLL created with Matlab and this does not seem to be possible. Correct?
I recently learned that any object with a GetAwaiter method returning an awaiter can be await-ed. This is true even if it's an extension method, meaning basically any object can be made await-able, if you so choose.
But is there a way to tell at runtime if an object is await-able? Normal reflection won't work, since it doesn't list an object's extension methods.
I don't have a particular need in mind when asking this question, I'm just curious if it's possible.
It's not possible because the information that the C# compiler uses to make that decision is gone.
In order to resolve extension methods we need to know the namespaces that are imported. That information is not available at runtime. It is a C#-only concept. The CLR does not know what a using is.
I cannot think of any reason you would want to see if an object is possibly awaitable at runtime because you can't act on that information. Maybe you could check if the object is a Task instead?
How can I read out all property names via reflection of an COM Object in C#?
I know how to get the property if I know the name.
comObject.GetType().InvokeMember("PropertyName", System.Reflection.BindingFlags.GetProperty, null, comObject, null);
but what is when I want to dump all properties?
PropertyInfo[] properties = t.GetProperties();
This way didn't work with Com-Objects. If I do a GetMembers() I get these Members:
Name: GetLifetimeService
Name: InitializeLifetimeService
Name: CreateObjRef
Name: ToString
Name: Equals
Name: GetHashCode
Name: GetType
regards Chris
You got the members of the __ComObject class, the underlying .NET class for an RCW.
COM has a wee bit support for reflection, as long as the COM coclass implements IDispatch, the Automation interface. Not unusual, it is the interface that scripting languages use to make calls. IDispatch.GetIDsOfNames() is always implemented, but you have to know the name of the member up front. IDispatch.GetTypeInfo() gives access to the type library for the coclass, but isn't always implemented. Translation of type library info to metadata is an imperfect art, the core reason why .NET wants you to do this upfront with Tlbimp.exe. If you want to pursue a runtime approach then you'll probably benefit from the source for the managed version of Tlbimp, available here.
Doing this up front at build time is always best, you do so by adding a reference to the type library (usually embedded in the executable file) or by running Tlbimp.exe yourself. Now you got a .NET interop wrapper class that has all of the members of the underlying COM coclass and interfaces. At which point you probably don't need reflection anymore :)
I've just published a CodeProject article about how to do Reflection with IDispatch-based COM objects. The article provides a small C# DispatchUtility helper class that's easy to include in other projects. Internally, it uses a custom declaration of IDispatch and .NET's TypeToTypeInfoMarshaler to convert IDispatch's ITypeInfo into a rich .NET Type instance.
In your example, you could call DispatchUtility.GetType(comObject, true) to get back a .NET Type instance, which you could then call GetProperties or GetMembers on.
I've also provided a version of the DispatchUtility source code on StackOverflow in a response to How to enumerate members of COM object in C#?
I created a C# COM accessible dll that I want to consume in VB6
I was able to consume in VB6 my COM object with a hard reference to the TLB.
What I am trying to do now is to remove this reference and load it dynamically
I am creating it as follows:
Dim keylok As Object
Set keylok = CreateObject("MyClassLib.MyObject")
I get the Run-time error 424 "Object Required" once I hit the second line.
But when I create it as follows:
Dim keylok As MyObject
Set keylok = CreateObject("MyClassLib.MyObject")
It works fine.
I am not sure why would that make a difference. Anyway I cannot use the second one because I would still need to have the physical reference.
I tried also as a sort of debugging to write to file in my COM object constructor to if it really gets called. And yes it does, I'm even able to call other methods in my COM object sucessfully inside the constructor.
I was even able to load dynamically and consume it from another C# app using:
dynamic myObj = Activator.CreateInstance(Type.GetTypeFromProgID("MyClassLib.MyObject"));
Did any one encounter something like that before?
I found the solution with the help of #rskar input. So, I thought I'm gonna answer my question, in case any one faces the same problem.
My object didn't impelement IDsipatch. So all I had to do it to decorate my C# COM interface with InterfaceType(ComInterfaceType.InterfaceIsDual) So it implements both IUnknown and IDispatch.
Originally it was decorated with InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
I think you are going to require the .tlb anyway. COM objects need to be capable of being marshalled as the .Net hosting runs on a different thread to the VB6 runtime. The default marshalling uses information from the typelibrary to do this. IDIspatch has 4 methods and 2 of these are to do with accessing type information. So possibly if you removed the .tlb, when you create the IDispatch COM attempts to call up the ITypeInfo from this and dies failing to load the registered typelibrary. If you eliminate the .tlb you will become unable to be marshalled and likely you would have to provide a custom marshaller for your interface.
I have a dll with a method.
This method accepts an object parameter (in .net) in vb6 it is defined as a variant, which is a vector of strings.
How can I make the call to this method on .net passing an array of strings?
Please send me an example
thanks
Both parties have good support for COM. I can't tell from your question whether or not the call comes from .net or VB6, but either way it will be simplest to communicate with good old fashioned COM.