Is it possible for a called program to define new variables that can be accessed by the calling program upon return from the called program? I'm analyzing some Cobol code and see that after calling a program there is suddenly reference to a variable terminated in -RET-CODE which is not defined anywhere in the calling program.
UPDATE: It seems to be a variable defined in a copybook. See comments at the answer.
No, the called program cannot add variables to the calling program.
The compiler can pre-define internal special variables. For instance, in Microfocus Extend, the RETURN-CODE variable is always available and will be set to the value from the EXIT PROGRAM RETURNING return-value statement.
If you need more than just that numeric value, then you would call the subprogram with BY REFERENCE variables. You then define the variables in both programs, the calling program anywhere and the called program in the LINKAGE SECTION.
Related
To cast a JObject to a JList (or anything else, it doesn't matter, this is just an example), is just doing JList(MyJobject) a good way? I don't receive any error, but I'm not sure if it's the correct way to go.
When casting between different object types, you cannot use a plain type-cast. You must cast the JObject to ILocalObject and call its GetObjectID() method, and then pass that result to the Wrap() method of the destination class type, in this case TJList, eg:
For example:
var
MyJobject: JObject;
MyJList: JList;
MyJobject := ...;
MyJList := TJList.Wrap((MyJobject as ILocalObject).GetObjectID);
Or simpler (which is just a wrapper for the above):
var
MyJobject: JObject;
MyJList: JList;
MyJobject := ...;
MyJList := TJList.Wrap(MyJobject);
See What the purpose of doing (MyJobject as ILocalObject).GetObjectID
There are two possible problems with using plain typecast.
First, if particular Java class has not been initialized with previous Delphi code, its VMT table will not be initialized. Next, references returned by JNI calls are local references and they are only valid for the duration of particular native method.
JNI tips
Every argument passed to a native method, and almost every object
returned by a JNI function is a "local reference". This means that
it's valid for the duration of the current native method in the
current thread. Even if the object itself continues to live on after
the native method returns, the reference is not valid.
This applies to all sub-classes of jobject, including jclass, jstring,
and jarray. (The runtime will warn you about most reference mis-uses
when extended JNI checks are enabled.)
The only way to get non-local references is via the functions
NewGlobalRef and NewWeakGlobalRef.
If you want to hold on to a reference for a longer period, you must
use a "global" reference. The NewGlobalRef function takes the local
reference as an argument and returns a global one. The global
reference is guaranteed to be valid until you call DeleteGlobalRef.
Wrap solves both issues. It initializes Java class VMT if not already initialized and converts local JObject reference to global one.
Plain typecast can only work if class is initialized by some previous code and the local reference is not used outside native (Delphi) method that retrieved said reference.
That is why plain typecast used in JStringToString(JString(PurchaseDataList.get(I))) can work properly. JObject reference returned by get is immediately converted to Delphi string and JString VMT is already initialized at that point, being commonly used Java class.
When in doubt, using Wrap is safer, but it also takes more time than plain typecast.
Just wondering, since closure is a function that has references to variables/methods outside it's definition.
Every function closes over program's global variables (basically in every mainstream language, be it javascript/python/c/c+/whatever).
So, consequently, every function is a closure?
Edit: let me reemphasize, I'm not talking only about closures in javascript but in a more general context
Yes, exactly. As you've identified, every function in JavaScript is a closure over at least one context: The global context. That's how/why global variables work in JavaScript.
We don't normally call them closures unless they close over some other context and actually make use of the fact that they do, but you're quite right that at a technical level, they all are.
Every function closes over program's global variables (basically in every mainstream language, be it javascript/c/c+/whatever).
I wouldn't generalize that far, no. Different languages have different ways of implementing global variables. Whether functions in those languages are all "closures" is probably open for debate, so I've restricted my answer above to JavaScript.
closure is a function that has references to variables/methods outside its definition
No, this is a "function with free variables", not a "closure".
To quote wikipedia
...a closure is only distinct from a function with free variables when outside of the scope of the non-local variables, otherwise the defining environment and the execution environment coincide and there is nothing to distinguish these (static and dynamic binding can't be distinguished because the names resolve to the same values).
In other words, in some context, a closure is a reference to a function that binds variables from another context. Otherwise, it wouldn't make sense to call it a "closure".
I'd like to get a firmer grasp of how frequently the runtime in any language that requires one is being called. In this case, I'm specifically interested in knowing:
Of all the function calls getting executed on an OS X or iOS system in any given second (approximations are of course necessary) how many of those are Objective-C runtime functions (i.e. functions that are defined by the runtime)?
Of course it depends on your application, but in general the answer is "a whole lot". Like, a whole freaking lot.
If you really want to see numbers, I'd recommend using dtrace to log all runtime functions as they're called. This blog entry talks about how to do such a thing.
A lot. Here are just a few examples.
Every time you send a message, the actual message sending is done by a runtime function (this is in fact the most called runtime function in pretty much any objective C program).
NSObject class and protocol are not part of the standard library but part of the runtime, therefore any method that ends up executing to the default NSObject implementation is in fact executing runtime code.
Every time you execute a default property accessor (either read or write), that's part of the runtime.
If you use ARC, every time you access a weak reference (either for reading or writing it) that's a runtime function.
Objc runtime includes the C runtime, so anything that involves a C runtime function (for example passing a large structure by value or returning it) is in fact calling into the runtime.
and more.
I want to implement a function in a dll that accepts a record as a parameter and this record as a few fields that hold pointers to callback routines. Would this be safe?
Yes, it's perfectly safe to have a pointer to a record that holds other pointers.
Your title mentions methods, though. DLLs rarely request method pointers because method pointers only exist in Delphi and C++ Builder. DLLs written expecting other tools to be able to use them will request ordinary function pointers, so please beware that method pointers are not compatible with pointers to standalone subroutines. The compiler will usually balk if you try to mix them, but type-casting can quell that error message. As a rule of thumb, if you're type-casting a function pointer or method pointer, you're doing something wrong. If your type declarations and your function declarations are correct, you won't need to type-cast.
Likewise, if you're using the # operator to create a function pointer or method pointer, you're probably doing it wrong. In most cases, the compiler can detect and assign compatible code pointers automatically, without you telling it that there's a pointer. Using # may suppress some of Delphi's type checking.
I don't see why not. I think all the usual issues with procedure/method pointers apply, so the object needs to exist if it's a method pointer.
It is safe but there are two issues that you should be aware about :
Records that declared as local variables are stored in the stack and they go away when the function returns. You should consider to allocate/dispose them on the heap with new/dispose functions.
If the DLL will be used by a program developed in other than delphi (or maybe even different versions of delpi), you have to use packed records.
One nice thing about anonymous methods is that I can use variables that are local in the calling context. Is there any reason why this does not work for out-parameters and function results?
function ReturnTwoStrings (out Str1 : String) : String;
begin
ExecuteProcedure (procedure
begin
Str1 := 'First String';
Result := 'Second String';
end);
end;
Very artificial example of course, but I ran into some situations where this would have been useful.
When I try to compile this, the compiler complains that he "cannot capture symbols". Also, I got an internal error once when I tried to do this.
EDIT I just realized that it works for normal parameters like
... (List : TList)
Isn't that as problematic as the other cases? Who guarantees that the reference is still pointing to an alive object whenever the anonymous method is executed?
Var and out parameters and the Result variable cannot be captured because the safety of this operation cannot be statically verified. When the Result variable is of a managed type, such as a string or an interface, the storage is actually allocated by the caller and a reference to this storage is passed as an implicit parameter; in other words, the Result variable, depending on its type, is just like an out parameter.
The safety cannot be verified for the reason Jon mentioned. The closure created by an anonymous method can outlive the method activation where it was created, and can similarly outlive the activation of the method that called the method where it was created. Thus, any var or out parameters or Result variables captured could end up orphaned, and any writes to them from inside the closure in the future would corrupt the stack.
Of course, Delphi does not run in a managed environment, and it doesn't have the same safety restrictions as e.g. C#. The language could let you do what you want. However, it would result in hard to diagnose bugs in situations where it went wrong. The bad behaviour would manifest itself as local variables in a routine changing value with no visible proximate cause; it would be even worse if the method reference were called from another thread.
This would be fairly hard to debug. Even hardware memory breakpoints would be a relatively poor tool, as the stack is modified frequently. One would need to turn on the hardware memory breakpoints conditionally upon hitting another breakpoint (e.g. upon method entry). The Delphi debugger can do this, but I would hazard a guess that most people don't know about the technique.
Update: With respect to the additions to your question, the semantics of passing instance references by value is little different between methods that contain a closure (and capture the paramete0 and methods that don't contain a closure. Either method may retain a reference to the argument passed by value; methods not capturing the parameter may simply add the reference to a list, or store it in a private field.
The situation is different with parameters passed by reference because the expectations of the caller are different. A programmer doing this:
procedure GetSomeString(out s: string);
// ...
GetSomeString(s);
would be extremely surprised if GetSomeString were to keep a reference to the s variable passed in. On the other hand:
procedure AddObject(obj: TObject);
// ...
AddObject(TObject.Create);
It is not surprising that AddObject keeps a reference, since the very name implies that it's adding the parameter to some stateful store. Whether that stateful store is in the form of a closure or not is an implementation detail of the AddObject method.
The problem is that your Str1 variable is not "owned" by ReturnTwoStrings, so that your anonymous method cannot capture it.
The reason it cannot capture it, is that the compiler does not know the ultimate owner (somewhere in the call stack towards calling ReturnTwoStrings) so it cannot determine where to capture it from.
Edit: (Added after a comment of Smasher)
The core of anonymous methods is that they capture the variables (not their values).
Allen Bauer (CodeGear) explains a bit more about variable capturing in his blog.
There is a C# question about circumventing your problem as well.
The out parameter and return value are irrelevant after the function returns - how would you expect the anonymous method to behave if you captured it and executed it later? (In particular, if you use the anonymous method to create a delegate but never execute it, the out parameter and return value wouldn't be set by the time the function returned.)
Out parameters are particularly difficult - the variable that the out parameter aliases may not even exist by the time you later call the delegate. For example, suppose you were able to capture the out parameter and return the anonymous method, but the out parameter is a local variable in the calling function, and it's on the stack. If the calling method then returned after storing the delegate somewhere (or returning it) what would happen when the delegate was finally called? Where would it write to when the out parameter's value was set?
I'm putting this in a separate answer because your EDIT makes your question really different.
I'll probably extend this answer later as I'm in a bit of a hurry to get to a client.
Your edit indicates you need to rethink about value types, reference types and the effect of var, out, const and no parameter marking at all.
Let's do the value types thing first.
The values of value types live on the stack and have a copy-on-assignment behaviour.
(I'll try to include an example on that later).
When you have no parameter marking, the actual value passed to a method (procedure or function) will be copied to the local value of that parameter inside the method. So the method does not operate on the value passed to it, but on a copy.
When you have out, var or const, then no copy takes place: the method will refer to the actual value passed. For var, it will allow to to change that actual value, for const it will not allow that. For out, you won't be able to read the actual value, but still be able to write the actual value.
Values of reference types live on the heap, so for them it hardly matters if you have out, var, const or no parameter marking: when you change something, you change the value on the heap.
For reference types, you still get a copy when you have no parameter marking, but that is a copy of a reference that still points to the value on the heap.
This is where anonymous methods get complicated: they do a variable capture.
(Barry can probably explain this even better, but I'll give it a try)
In your edited case, the anonymous method will capture the local copy of the List. The anonymous method will work on that local copy, and from a compiler perspective everything is dandy.
However, the crux of your edit is the combination of 'it works for normal parameters' and 'who guarantees that the reference is still pointing to an alive object whenever the anonymous method is executed'.
That is always a problem with reference parameters, no matter if you use anonymous methods or not.
For instance this:
procedure TMyClass.AddObject(Value: TObject);
begin
FValue := Value;
end;
procedure TMyClass.DoSomething();
begin
ShowMessage(FValue.ToString());
end;
Who guarantees that when someone calls DoSomething, that the instance where FValue points to still exists?
The answer is that you must guarantee this yourself by not calling DoSomething when the instance to FValue has died.
The same holds for your edit: you should not call the anonymous method when the underlying instance has died.
This is one of the areas where reference counted or garbage collected solutions make life easier: there the instance will be kept alive until the last reference to it has gone away (which might cause instance to live longer than you originally anticipated!).
So, with your edit, your question actually changes from anonymous methods to the implications of using reference typed parameters and lifetime management in general.
Hopefully my answer helps you going in that area.
--jeroen