(This post is related to two earlier posts by me, "Linking Ada to Pascal" and 'Where is documentation for "new argument to _p_initialize (@)" PCStrings.')
I have not been able to solve the problem when calling _p_initialize from Ada. I still get the Ada compiler telling me, "too many arguments in call." I suspect that I might be passing the wrong _kinds_ of arguments but not the wrong number.
Here are the three relevant files:
<file adacallspascal.adb> with Ada.Text_IO; use Ada.Text_IO; with Ada.Command_Line; use Ada.Command_Line; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure adacallspascal is
procedure mypascalprocedure; pragma Import(Convention => C, Entity => mypascalprocedure);
procedure init_pascal_main_program; pragma Import(Convention => C, Entity => init_pascal_main_program, External_Name => "_p__M0_init");
procedure p_initialize; pragma Import(Convention => C, Entity => p_initialize, External_Name => "_p_initialize");
procedure p_finalize; pragma Import(Convention => C, Entity => p_finalize, External_Name => "_p_finalize");
Argument_Count_Plus_1 : integer := Argument_Count + 1; Command_Name_String : string := Command_Name; C_Command_Name_String : aliased string := Command_Name_String & ASCII.NUL; begin Put_Line ("Hello from adacallspascal."); Put(Argument_Count_Plus_1); New_Line; Put_Line(Command_Name_String);
-- Initialize the Pascal RTS. p_initialize (Argument_Count_Plus_1, C_Command_Name_String'access, null, 0); -- Line 29
init_pascal_main_program; mypascalprocedure; p_finalize; Put_Line ("Goodbye from adacallspascal."); end adacallspascal;
<file mypascalprogram.pas> program mypascalprogram(input, output);
{$gpc-main=dummy}
procedure mypascalprocedure; attribute( name = 'mypascalprocedure'); begin writeln('Hello from mypascalprocedure.'); end;
begin {When exported to Ada, this part should not be called.} writeln('In mypascalprogram; error if calling from Ada.'); end.
<The commands> gpc -c mypascalprogram.pas gnatmake adacallspascal.adb -gnatf -largs mypascalprogram.o / Developer/Pascal/gpc344d2/lib/gcc/powerpc-apple-darwin8/3.4.4/libgpc.a
<Output from attempting to compile> gcc -c -gnatf adacallspascal.adb adacallspascal.adb:29:05: too many arguments in call gnatmake: "adacallspascal.adb" compilation error
Jerry
lanceboyle@qwest.net wrote:
I have not been able to solve the problem when calling _p_initialize from Ada. I still get the Ada compiler telling me, "too many arguments in call." I suspect that I might be passing the wrong _kinds_ of arguments but not the wrong number.
But where are the parameters in your declaration of _p_initialize in your Ada source ?
Regards,
Adriaan van Os
lanceboyle@qwest.net wrote:
[snip]
I have not been able to solve the problem when calling _p_initialize from Ada. I still get the Ada compiler telling me, "too many arguments in call." I suspect that I might be passing the wrong _kinds_ of arguments but not the wrong number.
Does GNAT support the Interfaces.C package as described in the Ada 95 LRM "B.3 Interfacing with C" http://www.adahome.com/LRM/95/rm95html/rm9x-B-03.html? If GNAT does support it, that seems to me to be the easiest way to get your Pascal interfacing going. It looks like all the necessary C types and conversions going to and from C are pre-canned for relatively easy Ada usage. (At the bottom of the reference web page, there's also an example of interfacing to C's "strcpy" function which might give a few tips on getting p_initialize working.)
procedure p_initialize; pragma Import(Convention => C, Entity => p_initialize,
External_Name => "_p_initialize");
I think you need to declare p_initialize with Ada to C equivalents of the four parameters for p_initialize that Adriaan has already discussed.
Ada isn't assembly language you know. Ada was designed so that "shot your foot off" errors like passing more (or fewer) parameters to external routines would be caught at compile time instead of at "really embarrassing" times like aircraft in flight. With that declaration, you've told the compiler p_initialize doesn't take any parameters. So, the compiler isn't going to let you "shot your foot off" by passing parameters to an external routine that you've declared takes no parameters.
Gale Paeper gpaeper@empirenet.com
Thanks for the helpful hints from both the Ada (GNAT) and Pascal (GPC) lists. This Ada and gcc newbie and C don'twannabe appreciates it!
I now have examples of Ada main program calling Pascal and Pascal main program calling Ada. I hope this helps someone.
Here is the cleanest and best-looking example, putting together hints from both lists. To Waldek Hebisch, your method of "pchar" and "ppchar" also works and is really the same, but using System.Address looks a little more Ada-like. Thanks Jim Hopper for your input--I need to study up on "aliased".
Sorry for the cross-post.
Jerry
<Ada main program> with Ada.Text_IO; use Ada.Text_IO; with Ada.Command_Line; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with System;
procedure Ada_Calls_Pascal is
Gnat_argc : aliased Integer; pragma Import (C, Gnat_argc); Gnat_argv : System.Address; -- Just get the base address to argv, like C pragma Import (C, Gnat_argv);
Gnat_envp : System.Address; -- Same for envp. pragma Import (C, Gnat_envp);
procedure MyPascalProcedure (anInteger : Integer); pragma Import(Convention => C, Entity => MyPascalProcedure);
procedure p_initialize( Number_of_Arguments : Integer; Command_Vector, Environment_Variables : System.Address; Options : Integer); pragma Import(Convention => C, Entity => p_initialize, External_Name => "_p_initialize");
procedure init_pascal_main_program; pragma Import(Convention => C, Entity => init_pascal_main_program, External_Name => "_p__M0_init");
procedure p_finalize; pragma Import(Convention => C, Entity => p_finalize, External_Name => "_p_finalize");
Argument_Count_Plus_1 : Integer; Command_Name_String : String := Ada.Command_Line.Command_Name; -- C's argv[0]
begin Put_Line ("Hello from Ada_Calls_Pascal.");
-- Here is the "Ada way" of handling command line arguments. Argument_Count_Plus_1 := Ada.Command_Line.Argument_Count + 1; -- the usual C-style argc Put("Number of arguments counting the command name is "); Put(Argument_Count_Plus_1); New_Line;
Put_Line("Program is called " & Command_Name_String); Put_Line("Its arguments, if any, are:"); for Argument_Index in 1..Ada.Command_Line.Argument_Count loop Put_Line(Ada.Command_Line.Argument(Argument_Index)); -- C's argv[1...] end loop;
-- Show that we also can do things the "C way." Put("argc = "); Put(Gnat_argc); New_Line;
-- Initialize the Pascal runtime system before calling any Pascal routines. p_initialize (Gnat_argc, Gnat_argv, Gnat_envp, 0);
-- Initialize the user's Pascal main program. init_pascal_main_program;
-- Run a user Pascal procedure. MyPascalProcedure(42);
-- Finalize the Pascal world before leaving. p_finalize;
Put_Line ("Goodbye from Ada_Calls_Pascal."); end Ada_Calls_Pascal;
<Pascal called program> program MyPascalProgram(input, output);
{$gpc-main=dummy}
procedure MyPascalProcedure(anInteger : integer); attribute ( name = 'mypascalprocedure'); begin writeln('The integer from the Pascal procedure is: ', anInteger:1); end;
begin {When exported to Ada, this part should not be called.} writeln('In MyPascalProgram; error if calling from Ada.'); end.
Jerry (lanceboyle) wrote:
I have not been able to solve the problem when calling _p_initialize from Ada. I still get the Ada compiler telling me, "too many arguments in call." I suspect that I might be passing the wrong _kinds_ of arguments but not the wrong number.
I was able to successfully call Pascal from Ada using yours files, with the following modifications:
1) declared that _p_initialize take parameters:
type pchar is access character; type ppchar is access pchar;
....
procedure p_initialize (argc : integer; argv, envp : ppchar; options : integer); pragma Import(Convention => C, Entity => p_initialize, External_Name => "_p_initialize");
2) changed the call to use C pointers (I do not know how to convert Ada access to C pointer):
p_initialize (Argument_Count_Plus_1, --C_Command_Name_String'access, null, null, 0); -- Line 29
3) Added -lm to the linker command line