What's a unit?

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

What's a unit?

Mark Morgan Lloyd-5
Does a unit- rather than something it contains- have any sort of
representation which is recognisably distinct from an object?

I've got a situation where if a library (.dll or .so) is opened under
program control it is represented by an object, with entry points
expressed as methods. Alternatively, if it's statically linked then it's
represented by a unit, with entry points represented by procedures and
functions. That allows me to write things like

caps := LibCapShim.cap_get_proc;  // LibCapShim is object or unit
if caps <> nil then
   try
     caplist := capability;
     r := LibCapShim.cap_set_flag(caps, flag, 1, @caplist, Ord(value));

which is OK at the application level irrespective of how the program's
built.

What I can't do, without a conditional directive, is check whether the
object representing the library is nil (because the dll/so isn't
available). Instead I'm having to do

{$ifdef USE_DYNAMIC_LIBCAP }
   if LibCapShim = nil then      (* Initialisation failed        *)
     exit;
{$endif                    }
   caps := LibCapShim.cap_get_proc;

and so on. There's obviously ways around this, but they tend to rely on
adding validity functions outside the object. Is there any way of doing
something like

if LibCapShim is TObject then
   if LibCapShim = nil then      (* Initialisation failed        *)
     exit;

without the compiler objecting when it finds itself looking at a unit
name in isolation?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

ik-6
On Tue, Feb 19, 2013 at 3:31 PM, Mark Morgan Lloyd
<[hidden email]> wrote:

> Does a unit- rather than something it contains- have any sort of
> representation which is recognisably distinct from an object?
>
> I've got a situation where if a library (.dll or .so) is opened under
> program control it is represented by an object, with entry points expressed
> as methods. Alternatively, if it's statically linked then it's represented
> by a unit, with entry points represented by procedures and functions. That
> allows me to write things like
>
> caps := LibCapShim.cap_get_proc;  // LibCapShim is object or unit

It's a namespace. It can be a namespace of a unit, record, instance of
class or object.

> if caps <> nil then
>   try
>     caplist := capability;
>     r := LibCapShim.cap_set_flag(caps, flag, 1, @caplist, Ord(value));
>
> which is OK at the application level irrespective of how the program's
> built.
>
> What I can't do, without a conditional directive, is check whether the
> object representing the library is nil (because the dll/so isn't available).
> Instead I'm having to do
>
> {$ifdef USE_DYNAMIC_LIBCAP }
>   if LibCapShim = nil then      (* Initialisation failed        *)
>     exit;
> {$endif                    }
>   caps := LibCapShim.cap_get_proc;
>
> and so on. There's obviously ways around this, but they tend to rely on
> adding validity functions outside the object. Is there any way of doing
> something like
>
> if LibCapShim is TObject then
>   if LibCapShim = nil then      (* Initialisation failed        *)
>     exit;
>
> without the compiler objecting when it finds itself looking at a unit name
> in isolation?
>
> --
> Mark Morgan Lloyd
> markMLl .AT. telemetry.co .DOT. uk
>
> [Opinions above are the author's, not those of his employers or colleagues]
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Marco van de Voort
In reply to this post by Mark Morgan Lloyd-5
In our previous episode, Mark Morgan Lloyd said:
> Does a unit- rather than something it contains- have any sort of
> representation which is recognisably distinct from an object?

Maybe. But what it certain doesn't have is a runtime instance. unit is
mostly a compiletime concept, and the Delphi exceptions to that (mostly due to
package system) are not implemented.
 
> I've got a situation where if a library (.dll or .so) is opened under
> program control it is represented by an object, with entry points
> expressed as methods. Alternatively, if it's statically linked then it's
> represented by a unit, with entry points represented by procedures and
> functions. That allows me to write things like

No, that does not exist to my best knowledge. Delphi might have ways
for packages, but that is also shaky (and target dependent) at best.

The only way is to define a record with procedure variables for the static
case manually I guess.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Mark Morgan Lloyd-5
Marco van de Voort wrote:

> In our previous episode, Mark Morgan Lloyd said:
>> Does a unit- rather than something it contains- have any sort of
>> representation which is recognisably distinct from an object?
>
> Maybe. But what it certain doesn't have is a runtime instance. unit is
> mostly a compiletime concept, and the Delphi exceptions to that (mostly due to
> package system) are not implemented.
>  
>> I've got a situation where if a library (.dll or .so) is opened under
>> program control it is represented by an object, with entry points
>> expressed as methods. Alternatively, if it's statically linked then it's
>> represented by a unit, with entry points represented by procedures and
>> functions. That allows me to write things like
>
> No, that does not exist to my best knowledge. Delphi might have ways
> for packages, but that is also shaky (and target dependent) at best.
>
> The only way is to define a record with procedure variables for the static
> case manually I guess.

I admit that I felt fairly pleased with myself when I hit upon using
units/objects like this, but this is definitely one of the downsides.

OK, so is it possible to set up a constant extended record (i.e. the
work being done entirely at compilation time) that mimics an
instantiated object? Would

if LibCapShim is TObject then
..

be safe where LibCapShim could be either an object (possibly nil) or a
constant extended record?

As I said, there's ways around it and I'm not entirely averse to a
conditional directive. But I'm interested in whether there's an elegant
solution- even if I can't use it immediately due to compiler versions etc.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Mark Morgan Lloyd-5
In reply to this post by ik-6
ik wrote:

> On Tue, Feb 19, 2013 at 3:31 PM, Mark Morgan Lloyd
> <[hidden email]> wrote:
>> Does a unit- rather than something it contains- have any sort of
>> representation which is recognisably distinct from an object?
>>
>> I've got a situation where if a library (.dll or .so) is opened under
>> program control it is represented by an object, with entry points expressed
>> as methods. Alternatively, if it's statically linked then it's represented
>> by a unit, with entry points represented by procedures and functions. That
>> allows me to write things like
>>
>> caps := LibCapShim.cap_get_proc;  // LibCapShim is object or unit
>
> It's a namespace. It can be a namespace of a unit, record, instance of
> class or object.

Which I presume is a concept valid only within the compiler, and even if
it were accessible in some way would be little better than a conditional
directive.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Sven Barth-2
In reply to this post by Mark Morgan Lloyd-5
On 19.02.2013 15:18, Mark Morgan Lloyd wrote:

> Marco van de Voort wrote:
>> In our previous episode, Mark Morgan Lloyd said:
>>> Does a unit- rather than something it contains- have any sort of
>>> representation which is recognisably distinct from an object?
>>
>> Maybe. But what it certain doesn't have is a runtime instance. unit is
>> mostly a compiletime concept, and the Delphi exceptions to that
>> (mostly due to
>> package system) are not implemented.
>>
>>> I've got a situation where if a library (.dll or .so) is opened under
>>> program control it is represented by an object, with entry points
>>> expressed as methods. Alternatively, if it's statically linked then
>>> it's represented by a unit, with entry points represented by
>>> procedures and functions. That allows me to write things like
>>
>> No, that does not exist to my best knowledge. Delphi might have ways
>> for packages, but that is also shaky (and target dependent) at best.
>> The only way is to define a record with procedure variables for the
>> static
>> case manually I guess.
>
> I admit that I felt fairly pleased with myself when I hit upon using
> units/objects like this, but this is definitely one of the downsides.
>
> OK, so is it possible to set up a constant extended record (i.e. the
> work being done entirely at compilation time) that mimics an
> instantiated object? Would
>
> if LibCapShim is TObject then
> ..
>
> be safe where LibCapShim could be either an object (possibly nil) or a
> constant extended record?

You could try to overload the "is" operator for your to be defined
static record [AFAIK it should work]. E.g.

=== code begin ===

TLibCapShim = record
   cap_get_proc: tcap_get_proc;
   // ...

   class operator is (aLeft: TLibCapShim; aRight: TClass): Boolean; inline;
end;

class operator TLibCapShim.Is(aLeft: TLibCapShim; aRight: TClass): Boolean;
begin
   Result := False;
end;

=== code end ===

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Mark Morgan Lloyd-5
Sven Barth wrote:

>> OK, so is it possible to set up a constant extended record (i.e. the
>> work being done entirely at compilation time) that mimics an
>> instantiated object? Would
>>
>> if LibCapShim is TObject then
>> ..
>>
>> be safe where LibCapShim could be either an object (possibly nil) or a
>> constant extended record?
>
> You could try to overload the "is" operator for your to be defined
> static record [AFAIK it should work]. E.g.
>
> === code begin ===
>
> TLibCapShim = record
>   cap_get_proc: tcap_get_proc;
>   // ...
>
>   class operator is (aLeft: TLibCapShim; aRight: TClass): Boolean; inline;
> end;
>
> class operator TLibCapShim.Is(aLeft: TLibCapShim; aRight: TClass): Boolean;
> begin
>   Result := False;
> end;
>
> === code end ===

Thanks Sven, looks interesting and I'll play with it presently. Can an
extended record's fields/methods be set up at compilation time, or do
they need to be done by code?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Sven Barth-2
On 19.02.2013 17:49, Mark Morgan Lloyd wrote:

> Sven Barth wrote:
>
>>> OK, so is it possible to set up a constant extended record (i.e. the
>>> work being done entirely at compilation time) that mimics an
>>> instantiated object? Would
>>>
>>> if LibCapShim is TObject then
>>> ..
>>>
>>> be safe where LibCapShim could be either an object (possibly nil) or a
>>> constant extended record?
>>
>> You could try to overload the "is" operator for your to be defined
>> static record [AFAIK it should work]. E.g.
>>
>> === code begin ===
>>
>> TLibCapShim = record
>>   cap_get_proc: tcap_get_proc;
>>   // ...
>>
>>   class operator is (aLeft: TLibCapShim; aRight: TClass): Boolean;
>> inline;
>> end;
>>
>> class operator TLibCapShim.Is(aLeft: TLibCapShim; aRight: TClass):
>> Boolean;
>> begin
>>   Result := False;
>> end;
>>
>> === code end ===
>
> Thanks Sven, looks interesting and I'll play with it presently. Can an
> extended record's fields/methods be set up at compilation time, or do
> they need to be done by code?
>

The example I've given was for the case that you load the functions
dynamically and use the procvars contained in the record. You could do
it this way as well:

=== code begin ===

TLibCapShim = record
   function cap_get_proc: tcaps;
end;

//...

function TLibCapShim.cap_get_proc: tcaps;
begin
   Result := UnitContainingImports.cap_get_proc;
end;

=== code end ===

You need to pay attention to call the correct functions, of course.

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Mark Morgan Lloyd-5
Sven Barth wrote:

>> Thanks Sven, looks interesting and I'll play with it presently. Can an
>> extended record's fields/methods be set up at compilation time, or do
>> they need to be done by code?
>>
>
> The example I've given was for the case that you load the functions
> dynamically and use the procvars contained in the record. You could do
> it this way as well:

Yes, that's pretty much what I'm already doing (courtesy of somebody's
Delphi NAG bindings). But what about the static case, i.e. can an
extended record be exposed as a constant in an ordinary unit (no DLLs
etc. involved) with the methods preinitialised?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Sven Barth-2
On 19.02.2013 18:08, Mark Morgan Lloyd wrote:

> Sven Barth wrote:
>
>>> Thanks Sven, looks interesting and I'll play with it presently. Can an
>>> extended record's fields/methods be set up at compilation time, or do
>>> they need to be done by code?
>>>
>>
>> The example I've given was for the case that you load the functions
>> dynamically and use the procvars contained in the record. You could do
>> it this way as well:
>
> Yes, that's pretty much what I'm already doing (courtesy of somebody's
> Delphi NAG bindings). But what about the static case, i.e. can an
> extended record be exposed as a constant in an ordinary unit (no DLLs
> etc. involved) with the methods preinitialised?
>

Yes, that will work. You can even initialize private fields (though I
don't know whether it needs to be in the same unit in that case...).

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

Mark Morgan Lloyd-5
Sven Barth wrote:

> On 19.02.2013 18:08, Mark Morgan Lloyd wrote:
>> Sven Barth wrote:
>>
>>>> Thanks Sven, looks interesting and I'll play with it presently. Can an
>>>> extended record's fields/methods be set up at compilation time, or do
>>>> they need to be done by code?
>>>>
>>>
>>> The example I've given was for the case that you load the functions
>>> dynamically and use the procvars contained in the record. You could do
>>> it this way as well:
>>
>> Yes, that's pretty much what I'm already doing (courtesy of somebody's
>> Delphi NAG bindings). But what about the static case, i.e. can an
>> extended record be exposed as a constant in an ordinary unit (no DLLs
>> etc. involved) with the methods preinitialised?
>>
>
> Yes, that will work. You can even initialize private fields (though I
> don't know whether it needs to be in the same unit in that case...).

Thanks, I'll experiment.

I'm surprised that somebody hasn't jumped on me and said that my error
checking's lousy: in fact there's plenty of checking in there but since
the code in question is being run early during a program's startup
(during which it might briefly be setuid root) any problems are being
noted for later display and worked around as far as possible.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: What's a unit?

shiruba2012
In reply to this post by Marco van de Voort
Hi,
On 2013/02/19, at 22:53, Marco van de Voort <[hidden email]> wrote:

> In our previous episode, Mark Morgan Lloyd said:
>> Does a unit- rather than something it contains- have any sort of
>> representation which is recognisably distinct from an object?
>
> Maybe. But what it certain doesn't have is a runtime instance. unit is
> mostly a compiletime concept, and the Delphi exceptions to that (mostly due to
> package system) are not implemented.

I've never though of it that way, but certainly that's true in the sense that if you want multiple objects, you can instantiate them at run time.  With a unit, you only get one.  In a sense, then, a unit is like a class with only class methods.  

In fact, even without having used those words - when I design a program for something where I know I will only need to track the state of a single item, I will often use units.  As soon as it's likely I will need to track the state of multiple items (particularly an unknown number of items), I have to think about using arrays i the unit, or just converting to objects.  
>
>> I've got a situation where if a library (.dll or .so) is opened under
>> program control it is represented by an object, with entry points
>> expressed as methods. Alternatively, if it's statically linked then it's
>> represented by a unit, with entry points represented by procedures and
>> functions. That allows me to write things like

Sadly this kind of thing has been one of the drawbacks of existing pascal implementations.  For example, you have program A which uses unit B.
You want to make B dynamic, so you convert it into a library (.so or .dll).  But you still want to use it in your program.  Back when I did this, at least, that required writing another shim unit which pulled in everything in the library.  It's understandable that you need the shim if the original program was written in C, etc., but a bit silly in the case where both were pascal.  Making full use of dynamic linking has been a pain in general.  (I prefer static linking most of the time, but there are advantages and disadvantages to both).  Your case isn't a lot different - but a unit can't do everything an object can anyway (as discussed above).

Probably the easiest thing for you to do is have the unit and the library both include a file with the object code.  That's not pretty, but it's better than double maintenance I suppose.
>
> No, that does not exist to my best knowledge. Delphi might have ways
> for packages, but that is also shaky (and target dependent) at best.
>
> The only way is to define a record with procedure variables for the static
> case manually I guess.

Thank you,
    Noah Silva
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal