comp.lang.ada
 help / color / mirror / Atom feed
* Directory Operations
@ 2008-11-03 16:27 andrei.krivoshei
  2008-11-03 17:33 ` Dmitry A. Kazakov
  2008-11-04 13:52 ` AndreiK
  0 siblings, 2 replies; 5+ messages in thread
From: andrei.krivoshei @ 2008-11-03 16:27 UTC (permalink / raw)


Hello.
I have a problem.
I need to write a DLL with a function, which returns the path to a
current directory under Windows XP.
I have't any problem with DLL itself, but when I try to use some
function from the package "GNAT.Directory_Operations" or
"Ada.Directories", I get the unexecutable DLL.
NOTE! The executable file is working, I talk only about DLL variant!

Thanks!

The code listing of my program is

========= Spec ============
with Interfaces.C.Strings; use Interfaces.C.Strings;

package FAD is

   procedure Pwd(Path_ptr: in out Chars_ptr );
   pragma Export(C, Pwd, "pwd");

end FAD;

========= Body ============
--  with Ada.Directories;
with Ada.Strings;
with GNAT.Directory_Operations;

package body FAD is
   package DOP renames GNAT.Directory_Operations;
   use Ada.Strings;

   procedure Pwd(Path_ptr: in out Chars_ptr ) is
--        use Ada.Directories;
      CStr: Chars_ptr;
      Path: String (1 .. 1024);
   begin
--      Path: String := "custom test string";  -- with this code line,
the DLL is executable
      Path := DOP.Get_Current_Dir;  -- with this code line, the DLL is
UNexecutable
      CStr := Null_Ptr; -- Value for test purposes only
      Path_ptr := CStr;
   end Pwd;

end FAD;



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

* Re: Directory Operations
  2008-11-03 16:27 Directory Operations andrei.krivoshei
@ 2008-11-03 17:33 ` Dmitry A. Kazakov
  2008-11-04 12:57   ` AndreiK
  2008-11-04 13:52 ` AndreiK
  1 sibling, 1 reply; 5+ messages in thread
From: Dmitry A. Kazakov @ 2008-11-03 17:33 UTC (permalink / raw)


On Mon, 3 Nov 2008 08:27:36 -0800 (PST), andrei.krivoshei@gmail.com wrote:

> I have a problem.
> I need to write a DLL with a function, which returns the path to a
> current directory under Windows XP.
> I have't any problem with DLL itself, but when I try to use some
> function from the package "GNAT.Directory_Operations" or
> "Ada.Directories", I get the unexecutable DLL.
> NOTE! The executable file is working, I talk only about DLL variant!
> 
> Thanks!
> 
> The code listing of my program is
> 
> ========= Spec ============
> with Interfaces.C.Strings; use Interfaces.C.Strings;
> 
> package FAD is
> 
>    procedure Pwd(Path_ptr: in out Chars_ptr );

1. Why don't you use Ada convention returning plain String?

   function Pwd return String
  [   renames Ada.Directories.Current_Directory; -- Work is done ]

2. Should you keep it non-Ada, then

2.a. how is this supposed to work?
2.b. Where is the string allocated?
2.c. Who will dispose it? When?
2.d. What happens when called from multiple threads?

>    pragma Export(C, Pwd, "pwd");
> 
> end FAD;
> 
> ========= Body ============
> --  with Ada.Directories;
> with Ada.Strings;
> with GNAT.Directory_Operations;
> 
> package body FAD is
>    package DOP renames GNAT.Directory_Operations;
>    use Ada.Strings;
> 
>    procedure Pwd(Path_ptr: in out Chars_ptr ) is
> --        use Ada.Directories;
>       CStr: Chars_ptr;
>       Path: String (1 .. 1024);
>    begin
> --      Path: String := "custom test string";  -- with this code line,
> the DLL is executable
>       Path := DOP.Get_Current_Dir;  -- with this code line, the DLL is UNexecutable

This cannot work, since Get_Current_Dir'Length may differ from 1024.

>       CStr := Null_Ptr; -- Value for test purposes only
>       Path_ptr := CStr;

That will not work either because Path is allocated on the stack and
destroyed upon return. See questions 2.a-d.

>    end Pwd;
> 
> end FAD;

C programming is substantially more difficult, even if occasionally spelt
in Ada...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Directory Operations
  2008-11-03 17:33 ` Dmitry A. Kazakov
@ 2008-11-04 12:57   ` AndreiK
  2008-11-04 14:44     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 5+ messages in thread
From: AndreiK @ 2008-11-04 12:57 UTC (permalink / raw)


On 3 нояб, 19:33, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Mon, 3 Nov 2008 08:27:36 -0800 (PST), andrei.krivos...@gmail.com wrote:
> > I have a problem.
> > I need to write a DLL with a function, which returns the path to a
> > current directory under Windows XP.
> > I have't any problem with DLL itself, but when I try to use some
> > function from the package "GNAT.Directory_Operations" or
> > "Ada.Directories", I get the unexecutable DLL.
> > NOTE! The executable file is working, I talk only about DLL variant!
>
> > Thanks!
>
> > The code listing of my program is
>
> > ========= Spec ============
> > with Interfaces.C.Strings; use Interfaces.C.Strings;
>
> > package FAD is
>
> >    procedure Pwd(Path_ptr: in out Chars_ptr );
>
> 1. Why don't you use Ada convention returning plain String?
>
>    function Pwd return String
>   [   renames Ada.Directories.Current_Directory; -- Work is done ]
>

Thank you for this advice.

> 2. Should you keep it non-Ada, then
>
> 2.a. how is this supposed to work?
> 2.b. Where is the string allocated?
> 2.c. Who will dispose it? When?
> 2.d. What happens when called from multiple threads?
>
>

Yes I have to keep it in non-Ada, more exact I have to use it in the
"NI LabVIEW"
2.a The LabVIEW calls the functions from DLL.
2.b,c LabVIEW allocates the string.
2.d --- I don't now

May be I can use plain String instead of pointers, but it seems, that
the problem is more abstract from the problem of String
representation.
For readability I will describe it in the next message.

> >    pragma Export(C, Pwd, "pwd");
>
> > end FAD;
>
> > ========= Body ============
> > --  with Ada.Directories;
> > with Ada.Strings;
> > with GNAT.Directory_Operations;
>
> > package body FAD is
> >    package DOP renames GNAT.Directory_Operations;
> >    use Ada.Strings;
>
> >    procedure Pwd(Path_ptr: in out Chars_ptr ) is
> > --        use Ada.Directories;
> >       CStr: Chars_ptr;
> >       Path: String (1 .. 1024);
> >    begin
> > --      Path: String := "custom test string";  -- with this code line,
> > the DLL is executable
> >       Path := DOP.Get_Current_Dir;  -- with this code line, the DLL is UNexecutable
>
> This cannot work, since Get_Current_Dir'Length may differ from 1024.
>
> >       CStr := Null_Ptr; -- Value for test purposes only
> >       Path_ptr := CStr;
>
> That will not work either because Path is allocated on the stack and
> destroyed upon return. See questions 2.a-d.
>
> >    end Pwd;
>
> > end FAD;
>
> C programming is substantially more difficult, even if occasionally spelt
> in Ada...
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de

Thank you!



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

* Re: Directory Operations
  2008-11-03 16:27 Directory Operations andrei.krivoshei
  2008-11-03 17:33 ` Dmitry A. Kazakov
@ 2008-11-04 13:52 ` AndreiK
  1 sibling, 0 replies; 5+ messages in thread
From: AndreiK @ 2008-11-04 13:52 UTC (permalink / raw)


Now the problem not seems to be in string representaion.
The example code is below.
Calling the function "Test_DLL" from fad.dll without using
"Ada.Directories" works perfectly.
However, uncommenting the line <Path: String :=
Ada.Directories.Current_Directory;> gives non working variant.
Try to call the same function from the DLL now finishes by the DLL
crash.
The line <Path: String := Ada.Directories.Current_Directory;> do
nothing usefull in the example, but it must not invite the DLL to
crash.

Can somebody explain, what is wrong?
May be some compiler, builder, linker switches can be a cause of such
behaviour?
I am using the GNAT compiler from GPS+GNAT(MinGW) complect under
Windows XP.
The DLL was tested using the NI LabVIEW and "ExecDLL (http://
www.codeproject.com/KB/DLL/Execute_DLL_Function.aspx)"

Thanks for everybody for advices.

---------------------------
-- fad.ads ----------------
---------------------------
with Ada.Directories;

package FAD is

   function Pwd return String;   -- I don't use it now
   pragma Export(C, Pwd, "pwd");
   function Pwd return String renames
Ada.Directories.Current_Directory;

   function Test_DLL(A, B: in Integer) return Integer;
   pragma Export(C, Test_DLL, "Test_DLL");

end FAD;

---------------------------
-- fad.adb ----------------
---------------------------
package body FAD is

   function Test_DLL(A, B: in Integer) return Integer is
-- ==>  Path: String := Ada.Directories.Current_Directory;
   begin
      return A*B;
   end Test_DLL;

end FAD;



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

* Re: Directory Operations
  2008-11-04 12:57   ` AndreiK
@ 2008-11-04 14:44     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 5+ messages in thread
From: Dmitry A. Kazakov @ 2008-11-04 14:44 UTC (permalink / raw)


On Tue, 4 Nov 2008 04:57:17 -0800 (PST), AndreiK wrote:

> On 3 яПНяПНяПНяПН, 19:33, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> 2. Should you keep it non-Ada, then
>>
>> 2.a. how is this supposed to work?
>> 2.b. Where is the string allocated?
>> 2.c. Who will dispose it? When?
>> 2.d. What happens when called from multiple threads?
> 
> Yes I have to keep it in non-Ada, more exact I have to use it in the
> "NI LabVIEW"
> 2.a The LabVIEW calls the functions from DLL.
> 2.b,c LabVIEW allocates the string.
> 2.d --- I don't now

In this case it should be something like this. LabVIEW passes a buffer to
Ada (Path, equivalent to char *), and the length of the buffer (Length).
Then

with Ada.Characters.Latin_1;
with Ada.Directories;         use Ada.Directories;
with Interfaces.C;            use Interfaces.C;
with Interfaces.C.Strings;    use Interfaces.C.Strings;

procedure Pwd (Path : chars_ptr; Length : size_t) is
   Result : constant String := Current_Directory &
Ada.Characters.Latin_1.NUL;
begin
   if Result'Length > Length then
     ... -- What do you do when the buffer is too short?
   else
      Update (Path, 0, Result, False);
   end if;
end Pwd;

From C it is called like:

{
   char buffer [1024];

   pwd (buffer, sizeof (buffer));
   ...
}

However, you should really refer to LabVIEW documentation regarding the way
it passes strings around. Once you know it, you can interface Ada. The code
above is merely a wild guess about how the interface might look like.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

end of thread, other threads:[~2008-11-04 14:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-03 16:27 Directory Operations andrei.krivoshei
2008-11-03 17:33 ` Dmitry A. Kazakov
2008-11-04 12:57   ` AndreiK
2008-11-04 14:44     ` Dmitry A. Kazakov
2008-11-04 13:52 ` AndreiK

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