'Passing String from C to Ada via C Interpreter (VxWorks)
I'm trying to pass a string from C to Ada by using the C interpreter in a telnet window to a VxWorks box.
Interface.h
#pragma once
#ifdef _cplusplus
extern "C"
{
#endif
extern void Ada_SetNewAddress(char*);
extern "C" void SetNewAddrBroker(char* ipAddress);
#ifdef __cplusplus
}
#endif
Interface.cpp
#include "Interface.h"
#include <stdio>
extern "C" void SetNewAddrBroker(char* ipAddress)
{
printf("We passed the value -> %s", ipAddress);
Ada_SetNewAddress(ipAddress);
printf("Ada was called!\n");
}
Streamer.ads
with Interfaces.C;
with Interfaces.C.Strings;
package Streamer is
procedure Initialize;
procedure SetNewAddress(str : Interfaces.C.Strings.chars_ptr);
pragma Export (C, SetNewAddress, "Ada_SetNewAddress");
end Streamer;
Streamer.adb
package body Streamer is
Socket : Socket_Type;
DefaultAddr : String := "127.0.0.1";
Address : Sock_Addr_Type := (Family_Inet, Inet_Addr(DefaultAddr), 1024);
Buffer : Stream_Access;
procedure Initialize is
begin
Create_Socket(Socket, Family_Inet, Socket_Datagram);
Buffer := Stream(Socket, Address);
end;
procedure SetNewAddress(str : Interfaces.C.Strings.chars_ptr)
cstar : String := Interfaces.C.Strings.Value(str);
begin
Address := (Family_Inet, Inet_Addr(cstar), 1024);
Buffer := Stream(socket, Address);
end;
end Streamer;
When I call the C function SetNewAddrBroker("192.168.1.1") I get a 'data access' error, this is via telnet to the VxWorks machine that this code exists on, the Ada program is the main task, so I know it's not the missing "adainit() and adafinal()" calls. I can't figure out why it's throwing a random data access error. I can use putty or teraterm for the telnet client if that matters, both throw the same error.
THE ERROR OUTPUT
We passed -> 192.168.1.1
data access
Exception current instruction address: 0x002e3ab0
............
trcStack aborted: error in top frame
Shell task 'tShellRem1' restarted...
Examining, the instruction that threw the error
0x2e3ab0 stw r30,8(r9)
I do not know assembly but I imagine this is trying to store the string in a place that is too small?
I need to set the IP of the broker for the client at runtime, the Ada is the client, and the broker is just on my LAN. I want to be able to telnet to the Ada client and just update the ip address, but the only interface exposed to me is the C interpreter for the VxWorks box, so I'm stuck with interfacing with this.
VxWorks Version 6.3
Solution 1:[1]
Here is a suggestion on changing the code in https://codeshare.io/DZBnMO such that it still calls Ada from C (instead of signalling an Ada task), but gets the string from the C structure without using Secondary Stack, because all string variables now have a statically known length:
In package Streamer, change the declaration of GetNewAddress to be:
subtype String_15 is String (1 .. 15);
type String_15_Ptr is access all String_15;
function GetNewAddress return String_15_Ptr;
pragma Import ( .. as before .. );
In package body Streamer, change SetNewAddress as follows:
procedure SetNewAddress
is -- (this "is" was missing from codeshare, btw)
csize : constant Natural := Natural (GetNewAddressLen);
cstrptr : constant String_15_Ptr := GetNewAddress;
adaString : String_15;
begin
for I in 1 .. csize loop
adaString(I) := cstrptr(I);
end loop;
Address := (Family_Inet, Inet_Addr(adaString(1 .. csize)), 1024);
Buffer := Stream (Socket, Address);
end;
Note that I haven't compiled this code, but I hope it shows the method to avoid Secondary Stack: every global and local variable must have a static size, and so must all function return-value types, but it is possible to pass slices of dynamic size as parameters (because GNAT uses pass-by-reference there).
The suggested Ada code is maybe not fully portable, because it assumes a certain correspondence between C types like "char *" and Ada types like "String_15_Ptr", but on normal architectures I expect it to work.
By the way, your C code has a potential buffer-overflow bug: SetNewAddrBroker should use strncpy(), not strcpy().
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Niklas Holsti |
