Problem with ADA file executed by a c++(UsrAppInit

2019-08-17 07:53发布

I have a file build and compiled correctly in ADA (a simple Hello world). I want to execute the file .o from a c++ using taskspawn. To do that I have read that you must declare in the c++ something like that:

...

#include <taskLib.h>

/* Ada binder-generated main - ADA_MAIN is passed as a macro from the makefile */

extern void ADA_MAIN(void);

void UsrAppInit()

{

int stackSize = 0x80000;


int spawnFlags = VX_FP_TASK;

/* MAIN_TASK_NAME is passed as a macro from the makefile */
char * mainTaskName = (char *) MAIN_TASK_NAME;

int priority = 100;

/* Spawn Ada environment task */

taskSpawn(mainTaskName, priority, spawnFlags, stackSize,
(FUNCPTR) ADA_MAIN, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}

to complete the process I have declared the ADA_MAIN as a MACRO in makefile (in my case the makefile is makefile.mk)

(MAIN_ADA pathOfmyADAexe and MAIN_TASK_NAME "the procedure of the helloworld")

but the MACRO are not recognized in the process so I have error in compilation for MAIN_TASK_NAME and ADA_MAIN. Any suggestion about how am I missing? I could also do in different way but how?

1条回答
女痞
2楼-- · 2019-08-17 08:36

I don’t know about your ADA_MAIN, and you don't tell us what your MACRO is, so it's a little hard to talk about them. Also, it's a while since I used VxWorks (and, then, we were supported, so had access to a cross-compiler that did the build for us: and our main program was in Ada).

That said, your problem comes down to building a program with Ada components where the main program isn't in Ada.

Ada programs need elaboration. This is the process that calls in all the components of the runtime library and arranges for them to be initialized in the right order. What components, you ask? well, for instance, there's the obvious Ada.Text_IO; and there's the less-obvious things, such as exception handling.

The elaboration code is generated using gnatbind.

Given this hello.adb

with Ada.Text_IO;
procedure Hello is
begin
   Ada.Text_IO.Put_Line ("hello!");
end Hello;

you really need to supply a specification, as otherwise the compiler will generate a linker name such as __ada_hello; take control by hello.ads,

procedure Hello with
  Export,
  Convention => C,
  External_Name => "hello";

You'll be using a cross-compilation suite. The components are prefixed by the target name, e.g. powerpc-wrs-vxworks-gnatmake, arm-eabi-gnatbind, but I'll just use the bare component name below.

$ gnatmake -c hello.adb

which generates hello.o, hello.ali (if the program was more complicated, it'd compile the closure too).

Now bind:

$ gnatbind -n -Lhello -static hello.ali

where

  • -n : main program not in Ada
  • -Lhello: adainit, adafinal renamed helloinit, hellofinal
  • -static: pretty sure VxWorks doesn't support shared libraries?

generating b~hello.ads, b~hello.adb (depending on the compiler release, the ~ may be replaced by e.g. double underscore). Compile:

$ gnatmake -c b~hello.adb

Now, to call from C++. you need to tell the compiler about the symbols in the Ada code, in e.g. hello.h:

extern "C" {
  void helloinit();
  void hellofinal();
  void hello();
}

and then the main program in main.cc:

#include "hello.h"

int main() {
  helloinit();
  hello();
  hellofinal();
}

which leaves you with the C++ compile and link, which needs the Ada runtime in libgnat.a and (for tasking) libgnarl.a, and is of course very compiler- and installation-specific: here, on the macOS host, I used

$ g++ main.cc b~hello.o hello.o /opt/gcc-8.1.0/lib/gcc/x86_64-apple-darwin15/8.1.0/adalib/libgnat.a
$ ./a.out
hello!

Translating this to the VxWorks context, I'd say that you'd call helloinit() from your main program (you probably won't need hellofinal()), and pass hello to taskSpawn() in place of your ADA_MAIN.

查看更多
登录 后发表回答