Pascal question from non-Pascal programmer 
Author Message
 Pascal question from non-Pascal programmer

Hello, folks.

I am trying to use a DLL written in Pascal in my C program.  I believe my
problem is due to the var modifier.  If var is *not* present for a record
parameter, does this mean that the entire record is passed to the function
instead of being passed by address?

---

Here are the prototypes that are supplied in the DLL's documentation:

function CalcDiscID(CdToc: TCdToc): Cardinal;
function ReadCdTOC(CdRom: TCdRom; var Toc: TCdToc): Boolean;

---

record definitions:

TCdRom = record
  HaId      : Byte;
  Target    : Byte;
  Lun       : Byte;
  Vendor    : ShortString;
  ProductId : ShortString;
  Revision  : ShortString;
  VendorSpec: ShortString;
end;

TTOC = record
  M: Byte;
  S: Byte;
  F: Byte;
  AudioTrack: Boolean; // indicates if the track is an audio or data track
end;

TCdToc = record
  TracksOnCD: Byte;
  LeadOut   : TTOC;
  Tracks    : array[0..99] of TTOC;
end;

---

Here is what I have found out about data types:

Integer          long
Cardinal         unsigned long
Boolean          unsigned char
Shortstring      char[256]   (the length byte is at element 0)
Byte             unsigned char

---

How would a C guy go about prototyping these two functions?

Thank you!

                            -Ray.



Fri, 25 Feb 2005 11:35:42 GMT  
 Pascal question from non-Pascal programmer
Please do not use the group "comp.lang.pascal" any more.



Quote:
> Hello, folks.

> I am trying to use a DLL written in Pascal in my C program.  I believe
my
> problem is due to the var modifier.  If var is *not* present for a
record
> parameter, does this mean that the entire record is passed to the
function
> instead of being passed by address?

Correct.
If var is present: the address of the record is passed. If the value of
the record fields change inside the function, the stored values of the
record outside the procedure change as well.
If var is not present: a copy of the value contents of the record is
passed to the procedure. Inside the function one can use and modify the
fields of the record variabele called Toc. Upon entering the function the
field values are preset to the value of the record passed to the
function. Changing these fields inside the function has no effect for the
record stored outside.

<snip irrelevant how the records are defined>
It is unclear to me what kind of pascal is meant here.

Quote:

> Here is what I have found out about data types:

> Integer          long

Normally in pascal
Integer= 2 bytes signed integer
Longint= 4 bytes signed integer
Word=2 bytes unsigned

Quote:
> Cardinal         unsigned long

never heard of this one. Look in the source to see how it is defined.

Quote:
> Boolean          unsigned char

one byte,
value
true : lsb=1
false: lsb=0

Quote:
> Shortstring      char[256]   (the length byte is at element 0)

in borland pascal types this would be called just STRING
If it is a null terminated string: Pchar.

Quote:
> Byte             unsigned char

in pascal
byte can have the unsigned values [0..255]
shortint = signed byte [-128..127]
char can have the values  ...'a','b','c'...etc
converting char to byte use ORD
converting byte to char use CHR

Quote:

> ---

> How would a C guy go about prototyping these two functions?

I don't know C very much but

In both cases of var or not va: pass a pointer to the record
In case of not var: copy the passed record to a new local record
parameter and work with that inside the function

Femme



Fri, 25 Feb 2005 17:55:51 GMT  
 Pascal question from non-Pascal programmer

Quote:
>unclear what kind of pascal is meant here

from the delphi help file

An integer type represents a subset of the whole numbers. The generic
integer types are Integer and Cardinal; use these whenever possible,
since they result in the best performance for the underlying CPU and
operating system. The table below gives their ranges and storage formats
for the current 32-bit Object Pascal compiler.

Type Range Format
Integer -2147483648..2147483647 signed 32-bit
Cardinal 0..4294967295 unsigned 32-bit
Fundamental integer types include Shortint, Smallint, Longint, Int64,
Byte, Word, and Longword.

Type Range Format
Shortint -128..127 signed 8-bit
Smallint -32768..32767 signed 16-bit
Longint -2147483648..2147483647 signed 32-bit
Int64 -2^63..2^63-1 signed 64-bit
Byte 0..255 unsigned 8-bit
Word 0..65535 unsigned 16-bit
Longword 0..4294967295 unsigned 32-bit
In general, arithmetic operations on integers return a value of type
Integer-which, in its current implementation, is equivalent to the 32-bit
Longint.

Femme



Fri, 25 Feb 2005 18:18:22 GMT  
 Pascal question from non-Pascal programmer
Hi Ray!

Quote:

> Hello, folks.

> I am trying to use a DLL written in Pascal in my C program.  I believe my
> problem is due to the var modifier.  If var is *not* present for a record
> parameter, does this mean that the entire record is passed to the function
> instead of being passed by address?

Correct.
AFAIR, the Pascal language defines all parameter passing to be
done "by value" _unless_ "VAR" is given, in which case it is
done "by reference".

However, this is a definition of semantics, not of implementation.
Even without "VAR", IMHO the passing might be by reference
(for performance reasons) as long as the function does not
modify the parameter, and even in that case the compiler might
ensure that a local copy is made.
Remember that the original aim of Pascal's creator was the
definition of clean, well-defined, abstract language for teaching
(which originally did not even support separate compilation of
modules ;-)

Then, several companies wrote and offered compilers with their
own, specific extensions to overcome restrictions they wanted
to get rid of.
(I do not follow that scene and hence know no details.)

Quote:

> [...]

> How would a C guy go about prototyping these two functions?

IMNSHO (I am just modifying our Pascal-to-C source code translator)
this is not trivial, and it depends on the compilers involved.

I have three proposals:
1) If your C compiler knows how to interface with that Pascal,
   that would be the best way.
2) If the Pascal compiler used to create the DLL can generate
   C source code, use that to generate a C prototype.
3) Otherwise, if you have a Pascal compiler that generates code
   which is binary compatible with your DLL (so that you can call it),
   and that compiler can generate C callable code, then you should
   write an interface module in Pascal.

Regards,
Joerg Bruehe

--
Joerg Bruehe, SQL Datenbanksysteme GmbH, Berlin, Germany
     (speaking only for himself)



Fri, 25 Feb 2005 20:59:02 GMT  
 Pascal question from non-Pascal programmer
Hello, Joerg.

Thanks for the reply.

I tried passing the C-equivalent of a record, which is a struct, by address
for the two functions that did not have the var attribute, but I was entitled
to a GPF.  The two other functions, which both did contain the var attribute
worked fine.

As you state, it would not be very efficient to pass an entire record instead
of passing a reference.  How to be sure?  I visited virtually every site found
in a Google search, but no site was definite about the mechanism used when
passing records with or without the var attribute.

Not being a Pascal programmer, I do not have a Pascal compiler.  This is a DLL
that I found on the Internet that reads a CD's TOC.  It was written in Pascal,
and the online documentation contains Pascal declarations as posted in my
original message.  I do not have access to the source code for this DLL.

I will try to contact the author.

Thanks!

                            -Ray.



Sat, 26 Feb 2005 00:14:20 GMT  
 Pascal question from non-Pascal programmer

Quote:

> Hello, Joerg.

> Thanks for the reply.

> I tried passing the C-equivalent of a record, which is a struct, by address
> for the two functions that did not have the var attribute, but I was entitled
> to a GPF.  The two other functions, which both did contain the var attribute
> worked fine.
> As you state, it would not be very efficient to pass an entire record instead
> of passing a reference.

The standard IIRC states something like that you can use parameters as an
ordinary local variable, yet that by value parameters shouldn't mess with
the original one. IOW you need a copy.

There are several ways to achieve this:
1 Copy the record as parameter itself.
2 caller copies record on the stack, and then passes reference. (IIRC TopSpeed
 did this)
3 Call by reference anyway.

3 is usually only done by very optimizing compilers that can guarantee that
the record isn't written by the callee or the procs that the callee calls.

Quote:
> Not being a Pascal programmer, I do not have a Pascal compiler.  This is a
> DLL that I found on the Internet that reads a CD's TOC.  It was written in
> Pascal,

Which one? Even more than under C, a lot of behaviour is compiler dependant,
specially if you go away from the direct standard, and start messing with
implementations.

Quote:
> and the online documentation contains Pascal declarations as
> posted in my original message.  I do not have access to the source code
> for this DLL.

If it is commercial, it probably is Delphi. Since Delphi uses regvars like
TopSpeed, it could be that it uses the "2" way. This means you should create
wrappers that copy the struct to a local var, and then pass that localvar to
the Delphi routine by ref. (pointer)


Sat, 26 Feb 2005 03:51:56 GMT  
 Pascal question from non-Pascal programmer
Hello, Marcos.

I think I am losing focus on my problem.  :)

I only wish to find out how var and non-var parameters are physically supplied
to the called function.

I have discovered that var parameters are passed by address.  Therefore, an
unsigned 32-bit is placed on the stack (or wherever) and the function will use
this to gain access to the original record.

What I am still not sure of is how non-var parameters are physically supplied
to the called function.  I don't believe that they are passed by address, else
the two functions that contain non-var parameters would have worked instead of
GPF-ing.

I don't care whether the function changes my records or not; I just want it to
not puke when I call it.

Thanks again for any insight.

                            -Ray.



Quote:
> This means you should create
> wrappers that copy the struct to a local var, and then pass that localvar to
> the Delphi routine by ref. (pointer)



Sat, 26 Feb 2005 04:08:22 GMT  
 Pascal question from non-Pascal programmer

Quote:

> Hello, Marcos.

> I think I am losing focus on my problem.  :)

> I only wish to find out how var and non-var parameters are physically supplied
> to the called function.

And I answered that there is no standard way. Each compiler can do it
differently, and one compiler can do different things depending on pragma's.

Quote:
> I have discovered that var parameters are passed by address.  Therefore,
> an unsigned 32-bit is placed on the stack (or wherever) and the function
> will use this to gain access to the original record.

That is true.

Quote:
> What I am still not sure of is how non-var parameters are physically supplied
> to the called function.

Re-read the previous message. There are 3 ways.

Quote:
>  I don't believe that they are passed by address, else the two functions
> that contain non-var parameters would have worked instead of GPF-ing.

Then
- try to disassemble a function from the DLL, (hard, but guaranteed success) or
- get info from the author.

- Try different things like push the entire rec on the stack, but align the
  rec on 0,4,8,16 bytes. (yes, params can be aligned on the stack too!)

Quote:
> I don't care whether the function changes my records or not; I just want
> it to not puke when I call it.

You don't know why it pukes.  If you pass the same record by ref, and the
program calls the function multiple times, it could still be the change
thing. (but I don't expect too)


Sat, 26 Feb 2005 05:39:48 GMT  
 Pascal question from non-Pascal programmer
Okay, thanks again.  I will give these suggestions a try.

                            -Ray.



Quote:
> Re-read the previous message. There are 3 ways.



Sat, 26 Feb 2005 07:07:54 GMT  
 Pascal question from non-Pascal programmer
Hi!


Quote:


> > Hello, Marcos.

> > I think I am losing focus on my problem.  :)

> > I only wish to find out how var and non-var parameters are physically supplied
> > to the called function.

> And I answered that there is no standard way. Each compiler can do it
> differently, and one compiler can do different things depending on pragma's.

That is the important point:
The language definition only specifies the semantics (the "what":
changes in "var" parameters propagate to the variable in the caller,
changes in non-"var" parameters remain within the function),
but the language definition does _not_ specify _how_ this is
achieved.

Quote:

> > I have discovered that var parameters are passed by address.  Therefore,
> > an unsigned 32-bit is placed on the stack (or wherever) and the function
> > will use this to gain access to the original record.

> That is true.

"Call by reference" (= pointer on the stack) is AFAIK the only
way really used for "var" parameters.

Quote:

> > What I am still not sure of is how non-var parameters are physically supplied
> > to the called function.

> Re-read the previous message. There are 3 ways.

"Call by value" (= copy on the stack) is an obvious one, but there
are others as well.

Of course this causes problems when linking with objects from
other compilers / written in other languages.

HTH,
Joerg Bruehe

--
Joerg Bruehe, SQL Datenbanksysteme GmbH, Berlin, Germany
     (speaking only for himself)



Sat, 26 Feb 2005 17:22:06 GMT  
 Pascal question from non-Pascal programmer
I can definitely tell you how one Pascal compiler (Oregon Software's Pascal-2
implementation on the PDP-11) handled this.

When a function or procedure was called, the parameters for the procedure would be
placed on the stack.  If the parameter was an "ordinary" (i.e. not a VAR)
parameter, the parameter itself went on the stack.  Thus a record would take up
however much stack space the record required.  Similarly, an array of 20
characters would take 20 bytes of stack space.  If the parameter was a VAR
parameter, then its address was passed on the stack.

The called routine, of course, knew the format of the parameters.  It was thus
easy to pick off various parameters by using the proper offset to the stack.  Thus
if the first parameter was an integer, and if (r0) pointed to the bottom of the
parameter stack, it could be found at 0(r0).  On the other hand, if the first
parameter was a VAR of an integer, then it represented the address of the integer,

offset of r0).

This is how one implementation handled VAR parameters ...

Bob Schor
Pascal Enthusiast

Quote:

> Hello, Marcos.

> I think I am losing focus on my problem.  :)

> I only wish to find out how var and non-var parameters are physically supplied
> to the called function.

> I have discovered that var parameters are passed by address.  Therefore, an
> unsigned 32-bit is placed on the stack (or wherever) and the function will use
> this to gain access to the original record.

> What I am still not sure of is how non-var parameters are physically supplied
> to the called function.  I don't believe that they are passed by address, else
> the two functions that contain non-var parameters would have worked instead of
> GPF-ing.

> I don't care whether the function changes my records or not; I just want it to
> not puke when I call it.

> Thanks again for any insight.

>                             -Ray.



> > This means you should create
> > wrappers that copy the struct to a local var, and then pass that localvar to
> > the Delphi routine by ref. (pointer)



Sun, 27 Feb 2005 22:08:38 GMT  
 Pascal question from non-Pascal programmer
Thanks for the information.

                            -Ray.


Quote:
> I can definitely tell you how one Pascal compiler (Oregon Software's
Pascal-2
> implementation on the PDP-11) handled this.



Sun, 27 Feb 2005 22:42:16 GMT  
 Pascal question from non-Pascal programmer

Quote:

> I can definitely tell you how one Pascal compiler (Oregon Software's Pascal-2
> implementation on the PDP-11) handled this.

Are there PDP-11 Pascal implementations freely available? I have a shell
account and disc space on a PDP-11.

The original OS (RSX something) had a Pascal compiler, but now it is NetBSD
afaik.

Porting GPC/FPC to PDP-11 isn't an option :-)



Mon, 28 Feb 2005 00:43:59 GMT  
 Pascal question from non-Pascal programmer
Oregon Software made several Pascal compilers for the PDP-11.  They were bought out
by TauMetrics, which ceased to exist about a decade ago (give or take maybe 5
years).  Their product was the basis for DEC's MicroPower Pascal (which I think ran
on RSX).  There were two other Pascals for PDP-11s that I know about, something
from the National Bureau of Standards called NBS-Pascal, and one from Sweden known
as Swedish Pascal.  My experience is with the Oregon Software products,
particularly Pascal 1 and Pascal 2 for RT-11 (I own both).

Bob Schor
Pascal Enthusiast


Quote:

> > I can definitely tell you how one Pascal compiler (Oregon Software's Pascal-2
> > implementation on the PDP-11) handled this.

> Are there PDP-11 Pascal implementations freely available? I have a shell
> account and disc space on a PDP-11.

> The original OS (RSX something) had a Pascal compiler, but now it is NetBSD
> afaik.

> Porting GPC/FPC to PDP-11 isn't an option :-)



Mon, 28 Feb 2005 01:13:47 GMT  
 
 [ 14 post ] 

 Relevant Pages 

1. Short Term Non-Coding Pascal Project

2. non text files in pascal

3. EU Borland Pascal programmer required.(EU only apply)

4. Turbo Pascal Programmers Page

5. Need a Pascal programmer for a small project

6. Looking for Turbo Pascal Programmers on ICQ of MSN messager

7. ANNOUNCE: Turbo Pascal Programmers Page

8. ANNOUNCE: Turbo Pascal Programmers Page

9. DOS/V Programmers Using Turbo Pascal

10. Cobol/Pascal Programmers Needed

11. Delphi / Pascal Programmer Wanted

12. Help for all pascal programmers

 

 
Powered by phpBB® Forum Software