From: Georg Bauhaus on
Gerd wrote:
> christoph.grein(a)eurocopter.com schrieb:
>
>> Gerd wrote:
>>> The GNAT Users Guide say that the "_" and the "@16" is appended
>>> automatically for "__stdcall" (as far as I understood). And the
>>> function is declared as "__stdcall" in the header-file.
>> External_Name and Link_Name in pragma Import are optional. But if you
>> provide them, they must be exact (AFAICS).
>
> No. The Users guide say the "@nn" is always added, the "_" can be
> dropped by specifying a link name, but is added if not specified in
> external name.
>

FWIW, using ObjectAda and Windows function names it's the same,
the external name of the function must be given without underscore
and @suffix.

Using gcc on Windows I get the same linker error when I try to "just"
refer to a windows function in a simple C program.
From: Dmitry A. Kazakov on
On 18 May 2006 03:51:48 -0700, Gerd wrote:

>> BTW, is it a CAN-bus adapter APIs? Which vendor?
>
> Yes, it is. It's a "PEAK-Service GmbH, Darmstadt" device.

I see.

> Are there any CAN-bus bindings for Ada available on the net (for any
> vendor)?

I don't know of any. I should not be that difficult to create one from
scratch. [ We don't use them directly, it is too many (Vector, IXXAT,
Softing, National etc), so we have an abstraction layer. ]

I am not so sure that GNAT indeed adds forwarding "_" for stdcall. At least
the error message you get indicates that linker fails to find
"CAN_GetHwParam(a)16", also no "_" ahead. If I correctly remember, one
"PEAK-dongle" had plain ANSI C interface, but it was a time ago. I think
that Import (C,... should work.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Gerd on
I've found the reason. It seems to be a bug in GNAT (3.15p). It depends
on the underscore "_" in the external name.
If the external function has a name xyz then everything works fine, but
if the name contains an "_" line x_z, link reports an error.

I've patched the .lib (replace "_" by "X") and the .exe (replace "X"
back to "_") and now it works. But that's not a nice method. Does
anyone know how Aonix behaves in this case (function name in dll
contains underscore)?

Gerd

From: Steve on
"Gerd" <GerdM.O(a)t-online.de> wrote in message
news:1147934783.645893.274580(a)u72g2000cwu.googlegroups.com...
> Hi all,
>
> I tried to create my own Ada bindings for a dll, but I didn't succeed.
>

I haven't done this with GNAT, but I have done similar work with ObjectAda.
I have a few noted suggestions below.

>
> The C-header contains:
>
> DWORD __stdcall CAN_GetHwParam(
> HCANHW hHw,
> WORD wParam,
> void* pBuff,
> WORD wBuffLen);
>
>
> My Ada-spec look like this:
>
> with System;

with Interfaces;

>
> package CanApi2 is
>
> pragma Linker_Options ("-lCanApi2");
>
> subtype
> HCANHW is Integer;
>

You need to look up the definition of HCANHW to find out the size. I prefer
to use either:

Interfaces.Unsigned_16;
Interfaces.Unsigned_32;
Interfaces.Integer_16;
Interfaces.Integer_32;

Since you are working with an interface. Some people prefer to use types
defined in Interfaces.C, I prefer to be more explicit for interfacing.

> subtype
> Word is Integer;

Assuming you're working on Win32, this should be:

subtype Word is Interfaces.Unsigned_16;

>
> function CAN_GetHwParam (hHw : HCANHW; wParam : Word; pBuff :
> System.Address; wBuffLen : Word) return Integer;
>
> private
> pragma Import (Stdcall, CAN_GetHwParam, External_Name =>
> "CAN_GetHwParam");
> end CanApi2;
>
> The lib-file (CanApi2.lib) contains this names:
>
> _CAN_GetHwParam(a)16 __imp__CAN_GetHwParam(a)16 _CAN_SetHwParam(a)12
> __imp__CAN_SetHwParam(a)12
>
>
> And that's what I get when build my test-program:
>
> C:\Work\CAN>gnatmake cantest
> gcc -c cantest.adb
> gcc -c canapi2.ads
> gnatbind -x cantest.ali
> gnatlink cantest.ali
> ./cantest.o(.text+0x264):cantest.adb: undefined reference to
> `CAN_GetHwParam(a)16'
>
> gnatlink: cannot call C:\GNAT\bin\gcc.exe
> gnatmake: *** link failed.
>
> DLL2DEF shows this:
>
> EXPORTS
> CAN_GetHwParam
>
>
> So what's wrong with my code? Please help, thanks.
>
> Gerd
>

The other thing I have moved toward is loading the dll dynamically at run
time. If the dll is loaded automatically when the program runs,
uncontrolled meaningless error messages (to an end user) appear and the
program fails. By loading dynamically I can put out a meaningful error
message. It is also easier to troubleshoot.

Here is an example of a few code fragments I use to set up a dynamic
interface to adagraph.

type PutpixelAccType is access
function(X, Y, Hue : Integer) return Integer;
pragma Convention( C, PutpixelAccType );

PutpixelAcc : PutpixelAccType;

function To_PutpixelAcc is
new Ada.Unchecked_Conversion( WinDef.FarProc, PutpixelAccType );

PutpixelProcName : C.Char_Array := C.To_C( "PutPixel" );

procedure Put_Pixel (X, Y : in Integer; Hue : in Color_Type := White) is
Return_Value : Integer;
begin
if PutPixelAcc /= null then
Return_Value := PutPixelAcc(X, Y, Color_Type'Pos (Hue));
if Return_Value < No_Errors then
Make_Exception (Return_Value);
end if;
end if;
end Put_Pixel;

-----------------------------------------------

adagraphLibraryName : C.Char_Array := C.To_C( "adagraph.dll" );
begin
adagraphDll := System.Null_Address;
adagraphDll := WinBase.LoadLibrary( adagraphLibraryName(0)'access );
...
PutpixelAcc := To_PutpixelAcc( WinBase.GetProcAddress( adagraphDll,
PutpixelProcName(0)'access ) );
....

I hope this helps,

Steve
(The Duck)


First  |  Prev  | 
Pages: 1 2
Prev: tasksing and TCP sockets
Next: GWindows