array of const with cdecl procedure

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

array of const with cdecl procedure

ik-6
Hello,

I'm trying to write a shard library of my own that you can use with C
as well. I'm using mode fpc, and not objfpc.

I created something like this:

...
procedure varargs_example(params : array of consts); cdecl;
...

The compiler report an error:
Error:Type identifier expected
Fatal: Syntax error, ")" expected but "CONST" found


Please note that I need to access the "params" variable inside my code.
How can I implement it correctly with FPC 2.6.0 ?

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

Re: array of const with cdecl procedure

Sven Barth-2
On 11.11.2012 13:40, ik wrote:

> Hello,
>
> I'm trying to write a shard library of my own that you can use with C
> as well. I'm using mode fpc, and not objfpc.
>
> I created something like this:
>
> ...
> procedure varargs_example(params : array of consts); cdecl;
> ...
>
> The compiler report an error:
> Error:Type identifier expected
> Fatal: Syntax error, ")" expected but "CONST" found
>
>
> Please note that I need to access the "params" variable inside my code.
> How can I implement it correctly with FPC 2.6.0 ?

You can not write cdecl functions with variable argument lists in FPC.
You can only access such functions exported from C code. See also here:
http://wiki.freepascal.org/User_Changes_2.6.0#Array_of_const_parameters_and_cdecl_routines

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

Re: array of const with cdecl procedure

ik-6
On Sun, Nov 11, 2012 at 2:54 PM, Sven Barth <[hidden email]> wrote:

> On 11.11.2012 13:40, ik wrote:
>>
>> Hello,
>>
>> I'm trying to write a shard library of my own that you can use with C
>> as well. I'm using mode fpc, and not objfpc.
>>
>> I created something like this:
>>
>> ...
>> procedure varargs_example(params : array of consts); cdecl;
>> ...
>>
>> The compiler report an error:
>> Error:Type identifier expected
>> Fatal: Syntax error, ")" expected but "CONST" found
>>
>>
>> Please note that I need to access the "params" variable inside my code.
>> How can I implement it correctly with FPC 2.6.0 ?
>
>
> You can not write cdecl functions with variable argument lists in FPC. You
> can only access such functions exported from C code. See also here:
> http://wiki.freepascal.org/User_Changes_2.6.0#Array_of_const_parameters_and_cdecl_routines

I know this one, but here I'm the one who write the code that is
exported to C and not vice versa.
How can I write it in a way that C can also use it ?

>
> Regards,
> Sven
> _______________________________________________
> 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: array of const with cdecl procedure

Sven Barth-2
On 11.11.2012 13:58, ik wrote:

> On Sun, Nov 11, 2012 at 2:54 PM, Sven Barth <[hidden email]> wrote:
>> On 11.11.2012 13:40, ik wrote:
>>>
>>> Hello,
>>>
>>> I'm trying to write a shard library of my own that you can use with C
>>> as well. I'm using mode fpc, and not objfpc.
>>>
>>> I created something like this:
>>>
>>> ...
>>> procedure varargs_example(params : array of consts); cdecl;
>>> ...
>>>
>>> The compiler report an error:
>>> Error:Type identifier expected
>>> Fatal: Syntax error, ")" expected but "CONST" found
>>>
>>>
>>> Please note that I need to access the "params" variable inside my code.
>>> How can I implement it correctly with FPC 2.6.0 ?
>>
>>
>> You can not write cdecl functions with variable argument lists in FPC. You
>> can only access such functions exported from C code. See also here:
>> http://wiki.freepascal.org/User_Changes_2.6.0#Array_of_const_parameters_and_cdecl_routines
>
> I know this one, but here I'm the one who write the code that is
> exported to C and not vice versa.
> How can I write it in a way that C can also use it ?

Yes and this is exactly what the change states. You can not write
"varargs" functions in Pascal that can be accessed from C.

The only solution would be to basically do something like the TVarRec
record does: have a record of which one field is a "type specifier" and
the remaining is a union out of the different supported types. You then
pass a Pointer to the first element of an array of that type and the
length of the array to the Pascal function. The negative point is of
course that you'll need to instantiate, populate and afterwards free the
array you pass to the pascal function.

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

Re: array of const with cdecl procedure

Bernd K.
2012/11/11 Sven Barth <[hidden email]>:

> Yes and this is exactly what the change states. You can not write "varargs"
> functions in Pascal that can be accessed from C.

Wouldn't it be possible to write a function in pascal that declares a
simple longint parameter instead of the varargs and then inside the
function use the stack pointer (the address of that argument) to read
the entire list from the stack directly? Since in cdecl the caller
will clean up the stack after the function call this should not cause
any problems?

something along these lines (for example if a list of longints should
be passed):

procedure FakeVararg(dummy: LongInt);
var
  Start: PLongInt;
  First, Second, Third: LongInt;

begin
  Start := PLongInt(@dummy);

  First := Start[0];
  Second := Start[1];
  Third := Start[2];

end;

(or something very similar to this, not sure if the above code works
already, not tested)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: array of const with cdecl procedure

Jonas Maebe-2

On 11 Nov 2012, at 20:42, Bernd wrote:

> Wouldn't it be possible to write a function in pascal that declares a
> simple longint parameter instead of the varargs and then inside the
> function use the stack pointer (the address of that argument) to read
> the entire list from the stack directly?

No, because the C varargs calling convention does not simply pass the parameters on the stack on most platforms.


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

Re: array of const with cdecl procedure

Bernd K.
2012/11/11 Jonas Maebe <[hidden email]>:

> No, because the C varargs calling convention does not simply pass the parameters on the stack on most platforms.

Where else are the arguments if not on the stack? Everything I have
read so far about varargs and cdecl says they are on the stack.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: array of const with cdecl procedure

Jonas Maebe-2

On 11 Nov 2012, at 20:57, Bernd wrote:

> 2012/11/11 Jonas Maebe <[hidden email]>:
>
>> No, because the C varargs calling convention does not simply pass the parameters on the stack on most platforms.
>
> Where else are the arguments if not on the stack?

In registers.

> Everything I have
> read so far about varargs and cdecl says they are on the stack.

Then you probably only read about i386 ABIs (and maybe m68k).


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

Re: array of const with cdecl procedure

Bernd K.
2012/11/11 Jonas Maebe <[hidden email]>:

> Then you probably only read about i386 ABIs (and maybe m68k).

But a bunch of ifdefs should do the trick then, it should still be
possible to implement every possible implementation in pascal somehow.

Is there a document somewhere that specifies how exactly cdecl varargs
is implemented on the different platforms? I could no find anything.
Since fpc can *call* vararg functions the knowledge about how exactly
they are implemented on all the different platforms must exist
somewhere?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: array of const with cdecl procedure

Jonas Maebe-2

On 11 Nov 2012, at 21:17, Bernd wrote:

> 2012/11/11 Jonas Maebe <[hidden email]>:
>
>> Then you probably only read about i386 ABIs (and maybe m68k).
>
> But a bunch of ifdefs should do the trick then, it should still be
> possible to implement every possible implementation in pascal somehow.

No, it is not possible. There are no Pascal (or C, for that matter) expressions that map to particular registers on entry into the function.

> Is there a document somewhere that specifies how exactly cdecl varargs
> is implemented on the different platforms?

There is one such document per ABI. These individual ABI documents are located all over the web. E.g. the official x86-64 ABI can be found at http://www.x86-64.org/documentation/abi.pdf, while the one for Win64 can be found at http://msdn.microsoft.com/en-us/library/ms235286.aspx

> I could no find anything.
> Since fpc can *call* vararg functions the knowledge about how exactly
> they are implemented on all the different platforms must exist
> somewhere?

It's much easier to construct it on the caller side than on the callee side. On the caller side, the information can be statically determined at compile time based on the types and order of the passed parameters. On the callee side, the information has to be dynamically determined. Moreover, the location of a cdecl varargs parameter generally depends on the number *and* types of the previous varargs parameters, so an expressions such as params[i] or even params[1] could never be supported. That's why in C you also have to use the va_start/va_arg/va_copy/va_end intrinsics to sequentially walk all such parameters.


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

Re: array of const with cdecl procedure

Mark Morgan Lloyd-5
Jonas Maebe wrote:

>> Is there a document somewhere that specifies how exactly cdecl varargs
>> is implemented on the different platforms?
>
> There is one such document per ABI. These individual ABI documents are located all over the web. E.g. the official x86-64 ABI can be found at http://www.x86-64.org/documentation/abi.pdf, while the one for Win64 can be found at http://msdn.microsoft.com/en-us/library/ms235286.aspx

I started trying to make a list of resources at
http://wiki.lazarus.freepascal.org/Assembler_and_ABI_Resources but it's
still largely just placeholders.

--
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: array of const with cdecl procedure

Bernd K.
In reply to this post by Jonas Maebe-2
2012/11/11 Jonas Maebe <[hidden email]>:

> No, it is not possible. There are no Pascal (or C, for that matter) expressions that map to particular registers on entry into the function.

ok, my wording was wrong. What I really meant to say was that if I am
absolutely determined to find a solution because I have no influence
on the calling side then it would still be possible to implement such
a function using only the means that are available in fpc. When I said
"is possible in Pascal" I really wanted to say "is possible with fpc
alone without having to make a separate C wrapper, even if it becomes
ridiculously complicated". Because "impossible" is such an absolute
word and used much too often I usually tend to not accept it without
proof.

I could for example make it an asm procedure (with separate
implementation for each architecture) that first takes the fixed
arguments and then pushes all remaining argument registers (if any) to
the stack and then calls a pascal procedure (the same for all
architectures) with the fixed arguments and a pointer to the register
save area and the number of saved registers and another pointer to the
stack area where to continue looking for more arguments should the
registers be exhausted. And the next step (if needed more than once)
would be to try to factor out most (or all?) of this into some easily
callable/includable code that resembles the functionality of the
va_start, va_arg and va_end macros and hides all the ifdef ugliness.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal