通过 C 解释器 (VxWorks) 将字符串从 C 传递到 Ada
我正在尝试通过在telnet窗口中使用C解释器将字符串从C传递到ADA。
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");
}
arterer.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;
当我调用c函数setNewAddrBroker(“ 192.168.1.1”)时,我会收到'数据访问'错误,这是通过telnet到telnet to to to to to to to to t to vxworks计算机,此代码在此代码上存在, ADA程序是主要任务,因此我知道这不是丢失的“ Adainit()和adafinal()”的呼叫。我不知道为什么它会丢弃随机数据访问错误。我可以为Telnet客户端使用Putty或Teraterm,如果这很重要,则可以丢下相同的错误。
错误输出
We passed -> 192.168.1.1
data access
Exception current instruction address: 0x002e3ab0
............
trcStack aborted: error in top frame
Shell task 'tShellRem1' restarted...
检查的指示,说明了
0x2e3ab0 stw r30,8(r9)
我不知道的组件,但我想这是试图将字符串存储在一个太小的地方?
我需要在运行时为客户端设置经纪人的IP,ADA是客户端,经纪人就在我的LAN上。我希望能够将其远程链接到ADA客户端并更新IP地址,但是接触到我的唯一接口是VXWorks Box的C解释器,因此我坚持使用此功能。
VXWorks版本6.3
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
以下是更改 https://codeshare.io/DZBnMO 中的代码的建议,以便它仍然调用 Ada来自 C(而不是发出 Ada 任务信号),但从 C 结构获取字符串而不使用辅助堆栈,因为所有字符串变量现在都具有静态已知长度:
在包 Streamer 中,将 GetNewAddress 的声明更改为:
在包主体中Streamer,将 SetNewAddress 更改为如下:
请注意,我还没有编译此代码,但我希望它展示了避免二级堆栈的方法:每个全局和局部变量都必须具有静态大小,因此所有函数返回值类型都必须具有静态大小,但可以将动态大小的切片作为参数传递(因为 GNAT 使用引用传递)。
建议的 Ada 代码可能不完全可移植,因为它假设 C 类型(如“char *”)和 Ada 类型(如“String_15_Ptr”)之间存在某种对应关系,但在普通架构上,我希望它能够工作。
顺便说一句,您的 C 代码有一个潜在的缓冲区溢出错误:SetNewAddrBroker 应该使用 strncpy(),而不是 strcpy()。
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:
In package body Streamer, change SetNewAddress as follows:
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().