Instantiate Interface of Interop DLL - f#

I'm working with some Interop code and need to instantiate an interface.
The equivalent in C# is:
Interop.SomeInterface theInterface;
theInterface = new Interop.SomeInterface();
theInterface.SomeEvent += new SomeEventHandler(...);
How can I accomplish instantiating this interface in F#? Do I need to re-wrap this interop dll into something that F# can make sense of?

It is impossible to instantiate an interface. The C# compiler is pulling a trick by instantiating a class by looking up the implementer of the interface. This is done by the compiler examining the CoClassAttribute.
As far as I know, F# knows nothing about the CoClassAttribute, so you need to change your code so that it instantiates an actual class, not an interface.
You could figure out the class you need by looking at the CoClassAttribute on SomeInterface with Reflector, ILdasm, or any other metadata inspector. If the interop wrapper was generated using tlbimp or visual studio, usually the class will be named SomeInterfaceClass by convention.

Related

Delphi tstream: strange behaviour on create

I am new of Delphi. In the documentation of TStrem class, i read it is an abstract class.
So i think the compiler goes in error when i try to create it with
stream := TStream.Create();
Why not?
The Delphi language doesn't really have any formal concept of abstract class.
It is true that you can define a class to be abstract:
type
TMyClass = class abstract
end;
But you can perfectly well instantiate this class. In fact class abstract in Delphi is a feature used only by the long abandoned Delphi .net compiler.
A more useful definition of an abstract class is one that contains abstract methods. If you attempt to instantiate such a class, then a compiler warning will be emitted. Those warnings can be promoted to errors by way of a compiler option, if you wish.
When the documentation refers to TStream as being abstract it in fact means that it is "conceptually" abstract. In fact it does not even have any abstract methods, so by my definition above it is not abstract.
I'm really not sure why TStream does not contain abstract methods. I would suggest that the GetSize, SetSize, Read, Write and Seek should really be declared abstract. I suspect that if the class were being designed today then they would be declared abstract and likely they are not for historical reasons.
Instantiating TStream is a very common mistake made by programmers less experienced in the Delphi RTL. Once the mistake has been made a couple of times, the lesson is usually learnt. Unfortunately the system provides no easy way for this mistake to be flagged up. Each and every new programmer just has to learn the hard way.

OTL can't be compiled under D2007

I downloaded the OTL http://www.omnithreadlibrary.com/
and compile the D2007 grouproj, install the package, without problem.
I then create a simple console application that uses OtlParallel unit, of course, I add the OtlParallel and some other pas files to the project.
But it complains that Generics.Collections is not found.
The documentation says:
High-level abstractions are implemented in the OtlParallel unit. They are all created through the factory class Parallel. High-level code intensively uses anonymous methods and generics which makes Delphi 2009 the minimum supported version.
This us of both generics and anonymous methods makes this unit completely incompatible with Delphi 2007.
If you wish to use a construct like Parallel.For with Delphi 2007 and OTL then you will have to back-port OtlParallel yourself. Without anonymous methods this is very difficult to do and achieve the same fluid style of code. You would have to use procedural types instead of anonymous methods. And you would have to implement closures manually.
So instead of using
TProc = reference to procedure;
you would use
TMethod = procedure of object;
And then to implement this you create a class or record with a parameterless method. You'll need to add whatever state is needed as members of the type, and populate those members. That is in essence a manual implementation of a closure with variable capture. And you'll need to deal with lifetime. Make sure that the instances outlive the parallel loop.
Good luck!

I found the ComClass, now how do I reference it?

I've written a small COM Server in Delphi 2010 that acts as a plug-in into a retail application. The retail application looks for a "discover" interface which registers any number of additional interfaces calling TAutoObjectFactory.Create for each one. This is working just fine--all the plug-in interfaces function as designed.
But now I'd like to call a public method of one interface from another interface so I don't have to duplicate code. Seems simple enough, just call ComClassManager.ForEachFactory looking for the ClassID of the interface I need to use. Got that working, too!
But now that I found the class, I'm stumped by a seemingly trivial final step: how to use or cast the class (or class reference?) I've located to actually call one of its methods.
In the "FactoryProc" I've sent to ForEachFactory, I assume the ComClass property of TComObjectFactory is what I'm after, but it's of type TClass, a class reference to the actual class object to which it points (at least I hope I'm understanding this correctly). I'm a little fuzzy on class references and my attempts to cast or otherwise de-reference this property has resulted in access violations or compiler errors.
Any suggestions?
You're right in your comment, ComClassManager deals with classes, not instances. What you need is (your application-local implementation of) running object table (or something similar), so plugin instances can interact with each other.
How to actually implement it depends on what you really need, e.g. call methods on all running instances, or only on instances of specific classes.

Passing a class containing overridden virtual methods to a dll

I have an application and a dll, both written in Delphi 2006.
I have an class that descends from a base class and overrides several virtual methods.
The class is passed to the DLL via an exported method, the exported method only knows about the base class. I call the methods on the class from within the DLL the overridden methods are not invoked.
Is there something I need to do to get this to work? is is it simply not possible?
You can't create an object in one module and call its methods in a different module. By module I mean .exe/.dll.
If you wish to cross boundaries like this, then you need to use packages, COM or free functions. Packages look alluring but bind you into using the same compiler for all packages in the system. If that is not restrictive to you then go ahead and use packages. Otherwise use COM or free functions.

How to automatically implement inherited abstract methods in Delphi XE

Is it possible to let the IDE automatically implement inherited abstract methods in Delphi XE? In Java and C# IDEs it's a common functionality like pressing ALT+SHIFT+F10 in Visual Studio or ALT+RETURN in IntelliJ IDEA.
Without this I always have to look up manually which methods have to be implemented and copy their declarations, which really is something I shouldn't have to do nowadays!
You can use ctrl+space in the class declaration to get a list of all the methods you might want to override (or implement from an interface). It does however not tell you which is abstract but once you figured that out you will get the declaration for free by selecting the method(s) from the list.
And after that you can of course use class completion ctrl+shift+c to generate the code in implementation section.
No, the Delphi IDE doesn't have an automatic shortcut for this. But, you can use the compiler to make it easier on you.
Define your new class. Then put a line somewhere in your code that says TMyNewClass.Create(whatever). When the compiler parses this, if there are any unimplemented abstract methods on TMyNewClass, it will tell you about them in the compiler warnings.

Resources