Where is the definition of "TypeIdentifier" - delphi

I would need to write a function that performs operations in RTTI mode on data, of which I do not know a priori the type.
I tried to write a function like this:
function doSomething (T: TypeIdentifier): Boolean;
as when using the expression TypeInfo(T) he expects as a type parameter TypeIdentifier
But when I try to compile I get an error because the type TypeIdentifier not recognized.
Someone could explain me how I can do to send a data type of which I know the type only at runtime?
Thanks to the availability.
Enzo

TypeInfo is an intrinsic function that uses compiler magic. That is the compiler generates the code that implements the function rather than it being part of the runtime library.
You don't have access to such magic. You cannot create a function that accepts a type identifier in the manner of TypeInfo. So you need to make your function accept what TypeInfo returns, a pointer to the type info, PTypeInfo.
You'd call your function like this:
DoSomething(TypeInfo(SomeTypeIdentifier));
Now technically, you may notice that TypeInfo returns a value of type Pointer. That's because PTypeInfo is defined in another unit, TypInfo and the System unit where all intrinsics are defined is not allowed to use TypInfo. But as stated in the documentation linked above, TypeInfo returns a pointer to TTypeInfo.

Related

A common ancestor for of object delegates in Delphi

Is there some common ancestor for Delphi delegates which are declared with of object clause?
I need to find a common ancestor for TNotifyEvent and my custom delegate:
TMyEvent = procedure(Sender: TObject; msg: stringh); of object;
to make an universal method for firing these events.
Should I use Pointer? or TObject?
You need to get down and dirty with the implementation details for method pointers. These are stored as a so-called double pointer value. One pointer for the subject of the method call (the instance) and one pointer for the method itself (the code).
You can use the type TMethod from the System unit to represent method pointers. Its declaration looks like so (with the comparison operators removed for simplicity):
type
TMethod = record
Code, Data: Pointer;
end;
You need to use a typecast to make assignments between these types:
uses
System.Classes;
var
Event: TNotifyEvent;
Method: TMethod;
begin
Method := TMethod(Event);
TMethod(Event) := Method;
end.
Obviously none of this is type-safe so you need to ensure correctness. The compiler cannot help you. There is nothing like the checked type conversion operator, as, to work with method pointers. That is, it is up to you that when you cast from TMethod to a specific method pointer type, you have to make sure that the TMethod instance really is an instance of the method pointer type to which you cast. Think of this whole process as being analogous to casting from a typed pointer to an untyped pointer, and then back again.
Now, if you are going to store arbitrary method pointers into TMethod instances, that's fine. But what happens when you subsequently need to fire these methods. You need to know which type of method pointer is really behind each TMethod instance. So that you know how to cast it, what arguments it needs, and so how to call it. That's going to mean you have to store extra information about the true type of the method, alongside the raw method itself.
So, I think that I have perhaps answered the question that you asked, but I'm not sure it's going to be of much use to you. To understand that I think we'd really need to know more about what you are trying to achieve, and what information you have, when.
For instance, if you know the arguments that are to be passed to the method at the time you need to store it away, you could use variable capture and wrap it in an anonymous method. That would allow you to retain type-safety and avoid any of the rather dubious casts that I demonstrate above. Perhaps you need partial application, as a means of adapting your non-homogeneous method pointers to have the same interface. In which case again anonymous methods can help.

property OnProcessEvent: TOnProcessEventProc read FOnProcessEvent write FOnProcessEvent;

I have come across a below function in a delphi code. I am quite new to delphi.There are quite a few places in Delphi where this function is called. However I can't seem to find the definition of this function. Could someone please explain what this means.
property OnProcessEvent: TOnProcessEventProc read FOnProcessEvent write FOnProcessEvent;
That declaration is not a function, it is a property, or more specifically an event. In that same class, you will see a data member named FOnProcessEvent of type TOnProcessEventProc. If you look at the declaration of TOnProcessEventProc, you will see that it is an alias for a method pointer of a specific signature, eg:
type
TOnProcessEventProc = procedure(Sender: TObject; ... other parameters here ...) of object;
That means any non-static class method that matches that signature can be assigned to the OnProcessEvent event. And if the event is declared as published, such a method can even be assigned at design-time instead of in code at run-time.
In the code for the class that declares the event property, all it has to do is call FOnProcessEvent() as if it were a procedure, eg:
if Assigned(FOnProcessEvent) then
FOnProcessEvent(Self, ... parameter values here ...);
Whatever method is actually assigned to FOnProcessEvent, if any, will be called.

How to pass interface type/GUID reference to an automation method in Delphi

In Delphi you can pass class references around to compare the types of objects, and to instantiate them. Can you do the same with interface references being passed to a COM automation server?
For example, you can define a method taking a GUID parameter using the type library editor:
function ChildNodesOfType(NodeType: TGUID): IMBNode; safecall;
In this function I would like to return automation types that support the interface specified by NodeType, e.g.
if Supports(SomeNode, NodeType) then
result := SomeNode;
But the Supports call always fails, I tried passing in the Guids defined in the type library but none of the different types (Ixxx, Class_xxxx, IId_Ixxxx) seem to work.
The SysUtils unit comes with at least five overloads of Supports, and they all accept a TGUID value for their second parameters.
You can indeed pass interface types as parameters, but they're really just GUIDs. That is, when a function expects a TGUID argument, you can pass it the interface type identifier, such as IMBNode or IUnknown. For that to work, though, the interface type needs to include a GUID in its declaration, like this:
type
IMBNode = interface
['{GUID-goes-here}']
// methods and properties
end;
When the first parameter to Supports is an interface reference, the function calls its QueryInterface method. If it returns S_OK, then Supports return true; otherwise, it returns false. When the first parameter is an object reference, then it first calls the object's GetInterface method to get its IUnknown interface, and calls Supports on that like before. If it doesn't work that way, then it falls back to asking for the requested interface directly from GetInterface. If you've implemented QueryInterface correctly on your object, or if you've used the default implementation from TInterfacedObject, then everything should work fine.
If Supports never returns true for you, then you should revisit some assumptions. Are you sure your node really supports the interface you're requesting? Go make sure the class declaration includes that interface. Make sure QueryInterface is implemented properly. And make sure SomeNode actually refers to the node you're expecting it to.

Retrieve TProc from Generic Container

Just discovered something rather funny:
var
Queue : TQueue <TProc>;
MyProc : TProc;
...
MyProc := Queue.Dequeue;
I think you see what is intendend here. However, the compiler thinks I want to store the Queue.Dequeue method (type "procedure of object") in MyProc and reports an error
E2010 Incompatible Types: 'TProc' und 'Procedure of object'
The workaround I came up with goes like this
MyProc := TProc (Pointer (Queue.Dequeue));
Is there a more elegant solution?
There's a bit of syntactical ambiguity there about whether the name "Dequeue" refers to the function itself, or the function's return value. And since you're dealing with an anonymous method pointer which you can assign a normal function to, it's trying to interpret that as a function assignment, not a function result assignment. Casting it to a pointer is the wrong solution, as that would force the function assignment to go through, which would then cause all sorts of fun errors when you attempt to invoke MyProc.
The correct way to fix it is by removing the syntactical ambiguity. Put an empty parenthesis after Dequeue, so that the compiler is sure that you're calling the function and not simply referencing it by name, and then it'll work.
MyProc := Queue.Dequeue();
As Mason said, there's an ambiguity in the Delphi syntax. Where TFoo.Bar is a method, it's not clear that FooValue.Bar means to refer to the result of calling TFoo.Bar, or a method pointer (or reference) TFoo.Bar itself (with implied Self argument of FooValue).
In the comments of Mason's answer, Rob Kennedy seems to suggest that the compiler simply figure this out based on the types of everything involved. This isn't simple; the compiler already does a lot of work to figure out whether you mean to refer to a method pointer value or a method call. It actually parses expressions in a different way when the expected receiver is a method pointer (or reference, or function pointer) type. The effort is especially involved when overloads are brought into the picture: the compiler scans through every overload candidate and checks for method pointer types in every parameter position, and then parses arguments differently depending on whether or not that parameter position contains a function pointer in one of the overloads. Then, if an overload that expects a function pointer isn't matched, the compiler changes the parse tree from function pointer to method call. The overloading mechanism itself needs to figure out which to use when its doing value to parameter comparisons. It's pretty messy, and it would be great if we didn't make it messier.
A prefix-style operator like # or Addr() isn't much help in resolving this ambiguity, not least because functions may return function pointers, and so on; how many # do you need to inhibit implicit (no () necessary) calling to grab the right value out? So when anonymous methods were introduced, a change in the expression parsing was made: I introduced the possibility of using () to force an invocation.
You can read more about it here:
http://blog.barrkel.com/2008/03/odd-corner-of-delphi-procedural.html
and here:
http://blog.barrkel.com/2008/03/procedurally-typed-expressions-redux.html

Howto cast pointer to generic parameter type?

it's my first question here, glad to have found this site.
My question deals with the new Generics feature in Delphi 2009. Basically I tried to write a generic wrapper class for an existing hash map implementation. The existing implementation stores (String, Pointer) pairs, so in the wrapper class I have to cast between the generic parameter type T and the Pointer type and vice versa.
type THashMap <T : class> = class
private
FHashList : THashList;
...
end;
I thought of a cast like this (Value : T)
Value := (TObject (Ptr)) as T
But this doesn't work. The compiler tells me 'Operator not applicable to this operand type'.
Somebody has some hints? Thanks a lot in advance.
You need to take the address of the location of the generic type parameter type, then typecast this address to a pointer to the desired type, and then dereference this pointer and assign into the resulting location. For example:
PObject(#Value)^ := Ptr;
The reason you can't just typecast a value of type T, where T is unconstrained, is that the compiler doesn't know the size of T; normally, non-numeric typecasts can only convert values into types that are of the same size.
Unfortunately, the compiler is not smart enough to figure out that a class-type constraint means that T is guaranteed to be the same size as a pointer.
Also, there is an issue with current Delphi 2009 generics with creating pointers to type parameter types. Generic pointers are not supported by the compiler, but the compiler permits this syntax inside classes:
type
C<T> = class
type
PT = ^T; // UNSUPPORTED!
end;
This may work for certain scenarios - and can be helpful for your specific problem - but it only works by accident and is not generally supported. Use at your own risk.
Try this:
Value := TObject (Ptr)
No need to cast more, as assigning the TObject to the generic class type variable is valid :)
But I do not know the reason why you cannot use T for casting in the first place...

Resources