Prev: tasksing and TCP sockets
Next: GWindows
From: Georg Bauhaus on 18 May 2006 08:15 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 18 May 2006 08:32 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 19 May 2006 04:30 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 18 May 2006 23:25
"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) |