I have a function in C. This function imports an Ada function. Inside my Ada function I want to do Put_Line, and have it displayed in my console. So this means that I have to open a C_Stream inside of my Ada function?
-- PUT_LINE PROBLEM, the parent function is in C.
-- Therefore I need to open a stream?
-- method 1, writing directly to stdout.
C_Out_File : Ada.Text_IO.File_Type;
Ada.Text_IO.C_Streams.Open
(File => C_Out_File,
Mode => Ada.Text_IO.Out_File,
C_Stream => Interfaces.C_Streams.stdout);
Put_Line (C_Out_File, "Hello!");
-- method 2, use Set_Output so I don't have to define the file in Put_Line.
Ada.Text_IO.Set_Output(C_Out_File);
Put_Line("Hello without specifying file!");
-- will have to Set_Output back to Ada.Text_IO.Standard_Output to get the regular back.
Both of these methods do work and properly display, though I do not know if this is the optimal way.
What, exactly, do you mean by āoptimalā?
What do you want to optimize?
Hm, you know what works well for context-capture? Generics.
And you can combine that with scoping to automatically take care of resetting things, or if you need the generic-instantiation at library level use code similar to the ālast chance handlerā example. Another option would be using a Task, having one entry handle the writing/procedure internals, and another entry for shutting down and cleaning up.
It really is dependent upon the design of your mixed-language system.
C streams is a necessity because the main function is C. Calling Put_Line without opening a c stream leads to raised ADA.IO_EXCEPTIONS.STATUS_ERROR : System.File_IO.Check_Write_Status: file not open
Several hours of wisdom later: I initially thought this was an incorrect response to my question, but it seems that I wasnāt elaborating (right word?) the Ada runtime so that Standard_Output would correspond to the stdout of C. My blunder was not recognizing that the main loop was not owned by Ada, so all I needed to do was pass -n (no main loop implemented in Ada, gives me adainit() and adafinal()), import the said external functions in C, and then call it once right before my C main loop calls my ada functions, now Put_Line outputs to the console the same as it always should, without having to do my c_stream setup. Thanks. This explanation is for anyone else coming across this in the future, gave me a headache.
-n // to the gnat binder to tell it to generate adainit() and adafinal()
// Then in the C/CPP code :
extern "C"
{
void adainit ();
void adafinal ();
};
// pseudo example:
int main () {
adainit(); // properly elaborate Ada.Text_IO etc...
Call_Ada_Entry_Point();
adafinal();
return 0;
}
-- Now any Ada code that does Put_Line will automatically write to the console owned by the C loop.
I have no actual problem with functionality or performance. Iām probably after a unicorn solution that does not exist. [ 6 hours later⦠] As I was writing this response to you I think I may have found the āunicornā solution, see above code. Itās optimal to me because itās āsmallerā and a one time solution, that may also solve the true underlying problem. I think itās the most correct way to do it. The C_Stream setup that I had going solved the problem of the console not displaying Put_Line. But, the underlying problem was me not implementing/elaborating/bindinghellmyheadhurts correctly.
I will also take your generics into account for next time, as I have already invested too much time into my way! My poor comedy aside, thank you for the tip.