From: Brian Drummond <brian@shapes.demon.co.uk>
Subject: Re: Ada "library only" compiler ?
Date: Sun, 22 Jul 2012 17:54:02 +0000 (UTC)
Date: 2012-07-22T17:54:02+00:00 [thread overview]
Message-ID: <juhenq$sjq$1@dont-email.me> (raw)
In-Reply-To: 98bd035c-3da7-4c9b-b483-051399dc5b57@googlegroups.com
On Sat, 21 Jul 2012 20:25:48 -0700, Patrick wrote:
> Hi Brian
>
> Thanks for your feedback Yes, thankfully with the help of people on the
> list I can work in both directions with C and Ada now and as such could
> write code in Ada and export it as C for use with other languages like
> Lua.
I can now call Lua from Ada.
Calling Ada from Lua ought to work, but I haven't tried it yet.
I downloaded Lua 5.21 today and tried this (c) example
http://lua-users.org/wiki/SimpleLuaApiExample
I needed to modify the compile process a little (linking with -ldl) to
overcome missing "dlopen" etc functions; after that, it worked as
expected. Then I made a basic port of the example to Ada.
This port uses a "thin binding", which can be (mostly) auto-generated by
GCC, using the -fdump-ada-spec[-slim] option. (This assumes gcc4.6.1 or
later)
gcc -fdump-ada-spec ../lua-5.2.1/install/include/lua.h
gcc -fdump-ada-spec ../lua-5.2.1/install/include/lauxlib.h
gcc -fdump-ada-spec ../lua-5.2.1/install/include/lualib.h
This builds package spec files (lua_h.ads, etc) for these header files.
Without -slim, actually the transitive closure of all the headers they
include, which can get VERY large. (This is not a problem with the tools,
just a reflection of the disastrous character of C's #include mechanism)
It is probably better to use -slim, and collect the (few) missing
dependencies into one small additional package. But for Lua, the closure
only generated 11 files, so I didn't try for this experiment.
Now there are a few problems with this binding; two trivial, one large,
because -fdump-ada-spec cannot parse everything in every header file.
I am detailing these below in case you want to reproduce the result.
Small problems (minimising the dependencies would eliminate these):
(1) compiling lauxlib_h.ads reports
"lauxlib_h.ads:289:25: "FILE" not declared in "stdio_h"
Workaround : comment out the problematic declaration (type luaL_Stream)
in lauxlib_h.ads. (I can't see the problem)
(2) compiling libio_h.ads reports
libio_h.ads:49:28: "anon652_anon676_array" is undefined
libio_h.ads:58:27: "anon652_anon679_array" is undefined
which turns out to be missing declarations for fields in a record
type u_IO_FILE is record
...
u_shortbuf : aliased anon652_anon676_array;
...
u_unused2 : aliased anon652_anon679_array;
end record;
Considering that one of these fields is declared in C as
--------------------------------------------------------
/* Make sure we don't get into trouble again. */
char _unused2[15 * sizeof (int) - 4 * sizeof (void *)
- sizeof (size_t)];
--------------------------------------------------------
I can't blame -fdump-ada-spec for failing to translate it!
Workaround : add subtype declarations ahead of the record decln in
libio_h.ads, as follows... (size was experimentally determined)
subtype anon652_anon676_array is Interfaces.C.char_array (0 .. 0);
subtype anon652_anon679_array is Interfaces.C.char_array (0 .. 39);
type u_IO_FILE is record ...
Bigger problem : -fdump-ada-spec can't translate macros; they just don't
have enough context to define their meaning.
I have resolved this by adding a new package, lua_macros (below), to
define constants, procedures and functions to replace the missing macros.
(There are probably 150 missing macros; I have only replaced enough to
run this example, but the remainder are mostly boilerplate)
Then a straight port of the test program (below) works as expected.
I have left all the gory details explicit in the source; a few "use"
clauses would make it much more readable.
A better approach would be a thick binding, another package which uses
these, but hides all the C interface details internally and provides a
clean Ada interface to application code.
-------- output --------------------------------------------------
./test
The table the script received from the Ada main has:
1 2
2 4
3 6
4 8
5 10
Returning data back to Ada
Script returned: 3.00000E+01
Success
--------- source ---------------------------------------------------
with Interfaces.C.Strings; use Interfaces.C;
with lua_h;
with lauxlib_h;
with lua_macros;
with lualib_h; -- why didn't the C version need to #include lualib.h?
with Ada.Text_Io; use Ada.Text_Io;
-- http://lua-users.org/wiki/SimpleLuaApiExample
procedure test is
status, result : Interfaces.C.int;
sum : Interfaces.C.double;
L : lua_macros.lua_State_Ptr;
begin
L := lauxlib_h.luaL_newstate;
lualib_h.luaL_openlibs(L); -- /* Load Lua libraries */
status := lua_macros.luaL_loadfile(L,
Strings.New_String("script.lua"));
if status /= 0 then
-- If something went wrong, error is at the top of the stack
Put_Line("Couldn't load file: " &
Strings.Value(lua_macros.lua_tostring(L, -1)));
raise Program_Error;
end if;
lua_macros.lua_newtable(L);
for i in 1 .. 5 loop
lua_h.lua_pushnumber(L, double(i)); -- /* Push the table
index */
lua_h.lua_pushnumber(L, double(i*2)); -- /* Push the cell value
*/
lua_h.lua_rawset(L, -3); -- /* Stores the pair in
the table */
end loop;
-- /* By what name is the script going to reference our table? */
lua_h.lua_setglobal(L, Strings.New_String("foo"));
-- /* Ask Lua to run our little script */
result := lua_macros.lua_pcall(L, 0, lua_macros.LUA_MULTRET, 0);
if result /= 0 then
Put_Line("Failed to run script: "&
Strings.Value(lua_macros.lua_tostring(L, -1)));
raise Program_Error;
end if;
-- /* Get the returned value at the top of the stack (index -1) */
sum := lua_macros.lua_tonumber(L, -1);
Put_Line("Script returned:" & float'image(float(sum)));
lua_macros.lua_pop(L, 1); -- /* Take returned value off stack */
lua_h.lua_close(L); -- /* Cya, Lua */
Put_Line("Success");
end test;
--------- macro spec ---------------------------------------------------
with lua_h;
with System;
with Interfaces.C.Strings;
use Interfaces.C;
package lua_macros is
-- missing macros from lua_h
-- skipped empty struct lua_State ... lua.h
subtype lua_State_Ptr is System.Address;
-- /* option for multiple returns in 'lua_pcall' and 'lua_call' */
-- #define LUA_MULTRET (-1)
LUA_MULTRET : constant Interfaces.C.Int := -1;
-- #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
function lua_pcall ( L : lua_State_Ptr;
n : Interfaces.C.int;
r : Interfaces.C.int;
f : Interfaces.C.int )
return Interfaces.C.int;
-- #define lua_pop(L,n) lua_settop(L, -(n)-1)
procedure lua_pop (L : lua_State_Ptr; n : Interfaces.C.int);
-- #define lua_tonumber(L,i) lua_tonumberx(L,i,NULL)
function lua_tonumber (L : lua_State_Ptr; i : Interfaces.C.int)
return lua_h.lua_Number;
-- #define lua_newtable(L) lua_createtable(L, 0, 0)
procedure lua_newtable (L : lua_State_Ptr);
-- #define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
function lua_tostring
(L : lua_State_Ptr;
i : Interfaces.C.int) return Interfaces.C.Strings.chars_ptr;
-- missing macros from lauxlib_h
-- #define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
function luaL_loadfile
(L : lua_State_Ptr;
f : Interfaces.C.Strings.chars_ptr ) return Interfaces.C.int;
end lua_macros;
--------- macro body ---------------------------------------------------
with lauxlib_h;
with lua_h;
with System;
with Interfaces.C;
package body lua_macros is
function lua_pcall ( L : lua_State_Ptr;
n : Interfaces.C.int;
r : Interfaces.C.int;
f : Interfaces.C.int )
return Interfaces.C.int is
begin
return lua_h.lua_pcallk(L, n, r, f, 0, NULL);
end lua_pcall;
procedure lua_pop (L : lua_State_Ptr; n : Interfaces.C.int) is
begin
lua_h.lua_settop(L, -(n)-1);
end lua_pop;
function lua_tonumber (L : lua_State_Ptr; i : Interfaces.C.int)
return lua_h.lua_Number is
begin
return lua_h.lua_tonumberx(L, i, NULL);
end lua_tonumber;
procedure lua_newtable (L : lua_State_Ptr) is
begin
lua_h.lua_createtable(L, 0, 0);
end lua_newtable;
function lua_tostring
(L : lua_State_Ptr;
i : Interfaces.C.int) return Interfaces.C.Strings.chars_ptr is
begin
return lua_h.lua_tolstring(L, (i), NULL);
end lua_tostring;
function luaL_loadfile
(L : lua_State_Ptr;
f : Interfaces.C.Strings.chars_ptr ) return Interfaces.C.int is
begin
return lauxlib_h.luaL_loadfilex
(L,f,Interfaces.C.Strings.Null_Ptr);
end luaL_loadfile;
end lua_macros;
--------- end ---------------------------------------------------
next prev parent reply other threads:[~2012-07-26 14:32 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-20 20:05 Ada "library only" compiler ? Patrick
2012-07-20 21:11 ` Niklas Holsti
2012-07-20 21:47 ` Ludovic Brenta
2012-07-20 22:25 ` Peter C. Chapin
2012-07-20 22:51 ` Ludovic Brenta
2012-07-21 0:32 ` Randy Brukardt
2012-07-21 12:39 ` Pascal Obry
2012-07-22 4:59 ` Shark8
2012-07-22 7:04 ` Pascal Obry
2012-07-22 10:17 ` Florian Weimer
2012-07-24 1:54 ` Randy Brukardt
2012-07-24 16:50 ` Pascal Obry
2012-07-24 18:01 ` Vasiliy Molostov
2012-07-24 21:30 ` Pascal Obry
2012-07-25 6:33 ` Vasiliy Molostov
2012-07-25 23:44 ` sbelmont700
2012-07-25 23:34 ` Randy Brukardt
2012-07-21 11:05 ` Niklas Holsti
2012-07-20 23:30 ` Patrick
2012-07-21 16:47 ` Niklas Holsti
2012-07-21 17:47 ` Patrick
2012-07-21 19:22 ` Simon Wright
2012-07-21 19:38 ` Patrick
2012-07-21 22:53 ` Brian Drummond
2012-07-22 3:25 ` Patrick
2012-07-22 17:54 ` Brian Drummond [this message]
2012-07-22 17:59 ` Brian Drummond
2012-07-22 18:44 ` Patrick
2012-07-22 21:03 ` Brian Drummond
2012-07-25 19:10 ` J-P. Rosen
[not found] ` <m2a9yrsbf5.fsf@nidhoggr.home>
[not found] ` <jui36a$hs0$1@dont-email.me>
2012-07-23 10:10 ` Simon Wright
2012-07-24 10:55 ` Brian Drummond
2012-07-22 21:25 ` Niklas Holsti
2012-07-22 22:00 ` Patrick
2012-07-22 21:18 ` Niklas Holsti
[not found] ` <olpj085ii9fpifpligh6jerghoaieiim1d@invalid.netcom.com>
2012-07-20 23:38 ` Patrick
2012-07-21 13:12 ` Niklas Holsti
2012-07-21 0:27 ` Randy Brukardt
2012-07-21 7:36 ` Dmitry A. Kazakov
2012-07-21 13:31 ` Niklas Holsti
2012-07-23 5:02 ` Miles Bader
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox