comp.lang.ada
 help / color / mirror / Atom feed
* Import C
@ 2004-01-26 13:48 Nando
  2004-01-26 14:30 ` Ludovic Brenta
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Nando @ 2004-01-26 13:48 UTC (permalink / raw)


Hello!!!
I need make an Ada application. I need send and receive some information
to/from the serial port communication (from PC to another device).

I don't know how to do it in Ada, but I know to do it in C/C++. I have found
the command "pragma inport(C, ...)" but I don't know how it works :((

My questions:
* Is enough the .C and .H files or I need the object file?
* How my Ada code know what file has my subrutine? i.e., where I say in my
Ada source code what files to include?

If you could give me a little example or documentation you would help me
very much.

Thanks you to every people.
Fernando






^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C
  2004-01-26 13:48 Import C Nando
@ 2004-01-26 14:30 ` Ludovic Brenta
  2004-01-27  5:47   ` Nando
  2004-01-26 14:51 ` Stephen Leake
  2004-01-28  9:30 ` Import C... Works!! but how does it work :/ Nando
  2 siblings, 1 reply; 8+ messages in thread
From: Ludovic Brenta @ 2004-01-26 14:30 UTC (permalink / raw)


"Nando" <nando89@terra.es> writes:

> Hello!!!
> I need make an Ada application. I need send and receive some information
> to/from the serial port communication (from PC to another device).
> 
> I don't know how to do it in Ada, but I know to do it in C/C++. I have found
> the command "pragma inport(C, ...)" but I don't know how it works :((
> 
> My questions:
> * Is enough the .C and .H files or I need the object file?

The Ada toolchain needs the object file only.  The .C and .H file are
useful only for you to see the prototype for the function you want.

> * How my Ada code know what file has my subrutine? i.e., where I say in my
> Ada source code what files to include?

The Ada compiler will not include anything.  The linker will link your
object file produced from C with the object files produced from Ada.

> If you could give me a little example or documentation you would help me
> very much.

You need to redeclare your C function in Ada, and then Import it.
Suppose yourt .H file has this prototype:

extern int foo(int a, int b);

then you need to write this in an Ada source file:

package Binding_To_External_Library is
   function Foo (A, B : Integer) return Integer; -- redeclare in Ada
   pragma Import (Convention => C, Entity => Foo, External_Name => "foo");
end Binding_To_External_Library;

The External_Name is the name that the function has in the object (not
C source) file.  Be careful with certain C compilers that insert an
underscore before the function name; the External_Name might be
"_foo".  I would advise not to import a C++ method because the name
mangling and the "this" pointer are sources of headaches.  Write a C
wrapper and import that instead.

If your function uses structures, you also need to declare a
corresponding type in Ada and use pragma Convention (C) on them.

There are many existing bindings which you can find on the web.  Thick
bindings are better.  A thick binding is one that replaces error codes
(returned from the C functions) into exceptions, that perform range
checking, and that are more type-safe than thin ones.  For example,
suppose your C header file defines these:

/* Values for parameter A passed to foo */
#define NO 0
#define YES 1
#define MAYBE 2
#define MAYBENOT 3

/* Your program will crash if B is larger than this.  You're warned. */
/* Oh, by the way, it will also crash if B < 0. */ 
#define MAX_VALUE_FOR_B 100

/* Values returned by foo */
#define ERROR -1
#define OK 0

extern int foo(int a, int b);

Then your thick binding would look like this:

package Thick_Binding is
   Foo_Error : exception;
   type Assessment is (No, Yes, Maybe, Maybe_Not);
   pragma Convention (C, Assessment);
   type Safe_Value_For_B is new Integer range 0 .. 100;
   pragma Convention (C, Safe_Value_For_B);
   procedure Foo (A : Assessment; B : Safe_Value_For_B);
   --  A type-safe procedure that always checks error codes.  The compiler
   --  ensures that you always call it with safe values for B.
end Thick_Binding;

package body Thick_Binding is
   procedure Foo (A : Assessment; B : Safe_Value_For_B) is
      --  Hide the ugly and error-prone C function
      function Internal (A, B : Integer) return Integer;
      pragma Import (C, Internal, "foo"); -- or maybe "_foo"
   begin
      if Internal (Assessment'Pos (A), Integer (B)) = -1 then
         raise Foo_Error;
      end if;
   end Foo;
end Thick_Binding;

HTH

-- 
Ludovic Brenta.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C
  2004-01-26 13:48 Import C Nando
  2004-01-26 14:30 ` Ludovic Brenta
@ 2004-01-26 14:51 ` Stephen Leake
  2004-01-27  5:56   ` Nando
  2004-01-28  9:30 ` Import C... Works!! but how does it work :/ Nando
  2 siblings, 1 reply; 8+ messages in thread
From: Stephen Leake @ 2004-01-26 14:51 UTC (permalink / raw)
  To: comp.lang.ada

"Nando" <nando89@terra.es> writes:

> Hello!!!
> I need make an Ada application. I need send and receive some information
> to/from the serial port communication (from PC to another device).

What operating system are you using? PCs run several operating systems
(Mac, Linux, Windows, Solaris, ...).

> I don't know how to do it in Ada, but I know to do it in C/C++. I
> have found the command "pragma inport(C, ...)" but I don't know how
> it works :((

I think you mean "pragma Import".

What manuals and/or books have you read?

> * Is enough the .C and .H files or I need the object file? 

You actually need the operating system serial interface object files,
not your object files or source files.

> * How my Ada code know what file has my subrutine? i.e., where I say
> in my Ada source code what files to include?

Hmm. Are you writing your own serial device driver? Or maybe you've
written a layer over the operating system layer, in C, and you want to
call that layer from Ada. If that's true, you do need to link in the
object files produced from your C code.

You specify what files to link on the linker command line. You need to
say what compiler you are using for me to be more specific.

> If you could give me a little example or documentation you would
> help me very much.

An example of a simple application using a serial port from Windows is
at http://www.toadmail.com/~ada_wizard/; get the "com_ports" file.

Hope this helps.

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C
  2004-01-26 14:30 ` Ludovic Brenta
@ 2004-01-27  5:47   ` Nando
  0 siblings, 0 replies; 8+ messages in thread
From: Nando @ 2004-01-27  5:47 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3913 bytes --]

Thans you very much!!! :)))

It's a very complete information, with examples and comments. I'm going to
try now everything you told. I think every thing is going to be all right ;)

Thanks again
    Fernando

"Ludovic Brenta" <ludovic.brenta@insalien.org> escribi� en el mensaje
news:m3wu7elr4e.fsf@insalien.org...
> "Nando" <nando89@terra.es> writes:
>
> > Hello!!!
> > I need make an Ada application. I need send and receive some information
> > to/from the serial port communication (from PC to another device).
> >
> > I don't know how to do it in Ada, but I know to do it in C/C++. I have
found
> > the command "pragma inport(C, ...)" but I don't know how it works :((
> >
> > My questions:
> > * Is enough the .C and .H files or I need the object file?
>
> The Ada toolchain needs the object file only.  The .C and .H file are
> useful only for you to see the prototype for the function you want.
>
> > * How my Ada code know what file has my subrutine? i.e., where I say in
my
> > Ada source code what files to include?
>
> The Ada compiler will not include anything.  The linker will link your
> object file produced from C with the object files produced from Ada.
>
> > If you could give me a little example or documentation you would help me
> > very much.
>
> You need to redeclare your C function in Ada, and then Import it.
> Suppose yourt .H file has this prototype:
>
> extern int foo(int a, int b);
>
> then you need to write this in an Ada source file:
>
> package Binding_To_External_Library is
>    function Foo (A, B : Integer) return Integer; -- redeclare in Ada
>    pragma Import (Convention => C, Entity => Foo, External_Name => "foo");
> end Binding_To_External_Library;
>
> The External_Name is the name that the function has in the object (not
> C source) file.  Be careful with certain C compilers that insert an
> underscore before the function name; the External_Name might be
> "_foo".  I would advise not to import a C++ method because the name
> mangling and the "this" pointer are sources of headaches.  Write a C
> wrapper and import that instead.
>
> If your function uses structures, you also need to declare a
> corresponding type in Ada and use pragma Convention (C) on them.
>
> There are many existing bindings which you can find on the web.  Thick
> bindings are better.  A thick binding is one that replaces error codes
> (returned from the C functions) into exceptions, that perform range
> checking, and that are more type-safe than thin ones.  For example,
> suppose your C header file defines these:
>
> /* Values for parameter A passed to foo */
> #define NO 0
> #define YES 1
> #define MAYBE 2
> #define MAYBENOT 3
>
> /* Your program will crash if B is larger than this.  You're warned. */
> /* Oh, by the way, it will also crash if B < 0. */
> #define MAX_VALUE_FOR_B 100
>
> /* Values returned by foo */
> #define ERROR -1
> #define OK 0
>
> extern int foo(int a, int b);
>
> Then your thick binding would look like this:
>
> package Thick_Binding is
>    Foo_Error : exception;
>    type Assessment is (No, Yes, Maybe, Maybe_Not);
>    pragma Convention (C, Assessment);
>    type Safe_Value_For_B is new Integer range 0 .. 100;
>    pragma Convention (C, Safe_Value_For_B);
>    procedure Foo (A : Assessment; B : Safe_Value_For_B);
>    --  A type-safe procedure that always checks error codes.  The compiler
>    --  ensures that you always call it with safe values for B.
> end Thick_Binding;
>
> package body Thick_Binding is
>    procedure Foo (A : Assessment; B : Safe_Value_For_B) is
>       --  Hide the ugly and error-prone C function
>       function Internal (A, B : Integer) return Integer;
>       pragma Import (C, Internal, "foo"); -- or maybe "_foo"
>    begin
>       if Internal (Assessment'Pos (A), Integer (B)) = -1 then
>          raise Foo_Error;
>       end if;
>    end Foo;
> end Thick_Binding;
>
> HTH
>
> --
> Ludovic Brenta.





^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C
  2004-01-26 14:51 ` Stephen Leake
@ 2004-01-27  5:56   ` Nando
  0 siblings, 0 replies; 8+ messages in thread
From: Nando @ 2004-01-27  5:56 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2270 bytes --]

Yes... I mean "pragma Import"... sorry for my english :))

I have download several documentation from
http://www.lawebdelprogramador.com, and searching in internet "ADA reference
manual". I also have read the documentation that my compiler has and I have
opened and studied the examples... but they don't word :((

My operating system is Windows XP, and I am writing my own serial device
driver.
I am using the "GNAT ADA 95 COMPILER"

Thank's you for the url :)) The simple code example is very usefull for me.
Now I try to call C routines from my Ada compiler.

Thanks you for your help.
Fernando


"Stephen Leake" <stephen_leake@acm.org> escribi� en el mensaje
news:mailman.19.1075128729.2270.comp.lang.ada@ada-france.org...
> "Nando" <nando89@terra.es> writes:
>
> > Hello!!!
> > I need make an Ada application. I need send and receive some information
> > to/from the serial port communication (from PC to another device).
>
> What operating system are you using? PCs run several operating systems
> (Mac, Linux, Windows, Solaris, ...).
>
> > I don't know how to do it in Ada, but I know to do it in C/C++. I
> > have found the command "pragma inport(C, ...)" but I don't know how
> > it works :((
>
> I think you mean "pragma Import".
>
> What manuals and/or books have you read?
>
> > * Is enough the .C and .H files or I need the object file?
>
> You actually need the operating system serial interface object files,
> not your object files or source files.
>
> > * How my Ada code know what file has my subrutine? i.e., where I say
> > in my Ada source code what files to include?
>
> Hmm. Are you writing your own serial device driver? Or maybe you've
> written a layer over the operating system layer, in C, and you want to
> call that layer from Ada. If that's true, you do need to link in the
> object files produced from your C code.
>
> You specify what files to link on the linker command line. You need to
> say what compiler you are using for me to be more specific.
>
> > If you could give me a little example or documentation you would
> > help me very much.
>
> An example of a simple application using a serial port from Windows is
> at http://www.toadmail.com/~ada_wizard/; get the "com_ports" file.
>
> Hope this helps.
>
> --
> -- Stephe
>





^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C... Works!! but how does it work :/
  2004-01-26 13:48 Import C Nando
  2004-01-26 14:30 ` Ludovic Brenta
  2004-01-26 14:51 ` Stephen Leake
@ 2004-01-28  9:30 ` Nando
  2004-01-28 14:24   ` Ludovic Brenta
  2004-01-29 17:12   ` Stephen Leake
  2 siblings, 2 replies; 8+ messages in thread
From: Nando @ 2004-01-28  9:30 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3198 bytes --]

Ok!!!
I am working for a day, but now I am able to work with routines written in C
code :))

I write you because may be the method is not so good as we want. I tell you:

This is the code:
PRUEBA.ADB
<<<<<<<< >>>>>>>>
    with ada.text_io, ada.integer_text_io;
    use ada.text_io, ada.integer_text_io;
    with u_prueba;
    use u_prueba;

    procedure prueba is
        a, b: integer;
        r : t_tipo;
    begin
        put_line("Holaaa");
        a := 2;
        b := 3;
        proc1(a, b);
        proc2(r, 5, 7);
        put(a); new_line;
        put(r.a); put(r.b); new_line;
    end;


U_PRUEBA.ADS
<<<<<<<< >>>>>>>>
    package u_prueba is
        type t_tipo is record
            a,b : integer;
        end record;

        procedure proc1(resultado: in out integer; entrada: in integer);
        procedure proc2(R: in out t_tipo; v1, v2: in integer);
    private
        pragma import (convention => C, Entity => proc1, External_name =>
"proc1");
        pragma import (convention => C, Entity => proc2, External_name =>
"proc2");
    end;

U_PRUEBA.H
<<<<<<<< >>>>>>>>
    #ifndef U_PRUEBA
    #define U_PRUEBA
        typedef struct {
            int a, b;
        } t_tipo;

        extern void proc1(int *, int);
        extern void proc2(t_tipo *, int, int);
    #endif


U_PRUEBA.C
<<<<<<<< >>>>>>>>
    #include "u_prueba.h"
        void proc1(int *resultado, int entrada)
        {
            *resultado = 2 * entrada;
        }

        void proc2(t_tipo *R, int v1, int v2)
        {
            R->a = v1;
            R->b = v2;
        }




Ok!! I need this names if I want everything works.
In "about" of my compiler apears: AdaGuide v. 6.60.2
When I compile my project, I can read GNATMAKE 3.13p

First, I compile the main file PRUEBA.ADB
Second, I build it... but I see I have errors:
    undefined reference to 'proc1'
    undefined reference to 'proc2'

Third, I go to the line command (run -> cmd), I go to the directory where
are my files keeped and I write the next sentence:
    gcc -c u_prueba.c

This line generate a new U_PRUEBA.O that overwrites the old one.

Fourth, I build again and every thing works like I want :))

Now I can run my exe file PRUEBA.EXE

I know that is not the way, but is the only mode that I can do it. Before,
my U_PRUEBA.ADS was called L_PRUEBA.ADS... but I was not able to do anything
:(
What I did wrongly?


Thanks you very much for your help, really :))
    Fernando




"Nando" <nando89@terra.es> escribi� en el mensaje
news:MU8Rb.2917532$uj6.7445107@telenews.teleline.es...
> Hello!!!
> I need make an Ada application. I need send and receive some information
> to/from the serial port communication (from PC to another device).
>
> I don't know how to do it in Ada, but I know to do it in C/C++. I have
found
> the command "pragma import(C, ...)" but I don't know how it works :((
>
> My questions:
> * Is enough the .C and .H files or I need the object file?
> * How my Ada code know what file has my subrutine? i.e., where I say in my
> Ada source code what files to include?
>
> If you could give me a little example or documentation you would help me
> very much.
>
> Thanks you to every people.
> Fernando
>
>
>





^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C... Works!! but how does it work :/
  2004-01-28  9:30 ` Import C... Works!! but how does it work :/ Nando
@ 2004-01-28 14:24   ` Ludovic Brenta
  2004-01-29 17:12   ` Stephen Leake
  1 sibling, 0 replies; 8+ messages in thread
From: Ludovic Brenta @ 2004-01-28 14:24 UTC (permalink / raw)



You have u_prueba.adb which compiles into u_prueba.o and u_prueba.ali.

You also have u_prueba.c which compiles into u_prueba.o.

You have a problem.  You should make sure your object files are
different.  For example:

gnatgcc -c u_prueba.c -o u_prueba_from_c.o
gnatmake prueba -largs u_prueba_from_c.o

HTH

-- 
Ludovic Brenta.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Import C... Works!! but how does it work :/
  2004-01-28  9:30 ` Import C... Works!! but how does it work :/ Nando
  2004-01-28 14:24   ` Ludovic Brenta
@ 2004-01-29 17:12   ` Stephen Leake
  1 sibling, 0 replies; 8+ messages in thread
From: Stephen Leake @ 2004-01-29 17:12 UTC (permalink / raw)
  To: comp.lang.ada

"Nando" <nando89@terra.es> writes:

> <snip code>
> 
> 
> Ok!! I need this names if I want everything works.

Others have pointed out your naming conflict.

> In "about" of my compiler apears: AdaGuide v. 6.60.2 When I compile
> my project, I can read GNATMAKE 3.13p

This is a very old compiler. The current version is 3.15p. What
operating system are you on?

> Third, I go to the line command (run -> cmd), I go to the directory where
> are my files keeped and I write the next sentence:
>     gcc -c u_prueba.c

You need to find a way to run make from AdaGide (I don't use it, so I
don't know how to do that). Then you need to set up a makefile that
will compile the C code by calling gcc directly, and the Ada code by
calling gnatmake. Then the makefile needs to link the C code together
with the Ada code by passing arguments to gnatmake.

Or, you can switch to GPS, which will let you define a project that
includes both Ada and C, and compile and link everything for you.

Hope this helps.

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-01-29 17:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-26 13:48 Import C Nando
2004-01-26 14:30 ` Ludovic Brenta
2004-01-27  5:47   ` Nando
2004-01-26 14:51 ` Stephen Leake
2004-01-27  5:56   ` Nando
2004-01-28  9:30 ` Import C... Works!! but how does it work :/ Nando
2004-01-28 14:24   ` Ludovic Brenta
2004-01-29 17:12   ` Stephen Leake

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox