• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

FreeBasic and third-party DLLs

Started by Mike Stefanik, July 20, 2008, 01:45:13 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Mike Stefanik

One thing about FreeBasic, and really anything that uses the MinGW linker, is that it's a bit of a pain in the rear to use third-party DLLs. They're COFF libraries, but they're not compatible with the COFF libraries that Visual C++ generates. So when you try to link against them, it either won't link (unresolved symbols) or the application GPFs (usually trying to access memory at some address like 0x80000001). So unlike languages like PowerBasic or VB where you can just specify the name of the DLL and be done with it, with FreeBasic you have to go through the exercise of downloading MinGW (because FreeBasic doesn't include all of the tools), using either pexports or reimp to dump the DLL exports, and then use dlltool to build "libmylibrary.dll.a" This is the kind of stuff that immediately turns off a lot of programmers who have no idea what the heck an import library is to begin with.

This is one of the reasons that I think PB has done well. They know who their core market is and they meet their needs. And they don't require their users to drop to a command line and enter:


reimp -d foobar.lib
dlltool -k -d foobar.def -l libfoobar.a


Just to be able to call some functions in a DLL. It's the sort of thing that's common in the UNIX world, but not to Windows programmers who primarily use BASIC. Anyway, that's the little end of my rant, but whenever I see a language that uses the tools in MinGW, I know I'm in for a ride on the merry-go-round of incompatibility and hoop-jumping.
Mike Stefanik
sockettools.com

Patrice Terrier

#1
Mike,

Freebasic uses decorated name as default, however i remember that Charles posted the syntax to use it the "standard" way.

What I can say with DLL(s) produced with PowerBASIC, is that i NEVER had any problem using them with another language.
And this include Dot.NET managed code, as well as WinDev's w-language.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

It's more than just the issue of decorated function names, although that's another potential hoop that you have to jump through. The problem seems to be that the linker doesn't quite understand Microsoft's COFF format, so you're forced to rebuild the import library using the MinGW tools. On the other hand, compilers like Pelles C (which is based on LCC) and Watcom C/C++ have no problem with Microsoft's libraries.
Mike Stefanik
sockettools.com

Marco Pontello

Quote from: Mike Stefanik on July 20, 2008, 01:45:13 PM
So unlike languages like PowerBasic or VB where you can just specify the name of the DLL and be done with it, with FreeBasic you have to go through the exercise of downloading MinGW (because FreeBasic doesn't include all of the tools), using either pexports or reimp to dump the DLL exports, and then use dlltool to build "libmylibrary.dll.a" This is the kind of stuff that immediately turns off a lot of programmers who have no idea what the heck an import library is to begin with.

Are you sure this is apply to the current state of FreeBASIC?
I used it with various Win32 DLLs (even ones written with PowerBASIC), and I had no need to do anything "special", it was as easy and straightforward as using the same libraries from PB.

Bye!

Mike Stefanik

#4
Quote from: Marco Pontello on July 20, 2008, 06:52:13 PM
Are you sure this is apply to the current state of FreeBASIC?
I used it with various Win32 DLLs (even ones written with PowerBASIC), and I had no need to do anything "special", it was as easy and straightforward as using the same libraries from PB.

That's because they include premade import libraries for the standard Windows DLLs. Look in the folder C:\Program Files\FreeBASIC\lib\win32 (or the equivalent of where you have it installed) and you'll see a bunch of libraries named things like libkernel32.dll.a so when you have a declaration like:


declare function GetComputerName lib "kernel32.dll" alias "GetComputerNameA" ( _
        byval lpBuffer as zstring ptr, _
        byref lpnSize  as uinteger _
        ) as integer


What that's really telling the compiler to do is link against libkernel32.dll.a, which is an export library that's compatible with the linker in MinGW. Try doing that with a third-party DLL for which you have no export library (no .a or .lib file), just the DLL itself, create a definition for it and try to compile the program. For example, if you had:


declare function BarFoo lib "foobar.dll" alias "BarFooA" ( _
        byval lpszFoo as zstring ptr, _
        byval nBar as integer _
        ) as integer


If you didn't create an import library named libfoobar.dll.a, the program wouldn't compile; you'd get a linker error that's something like "-lfoobar.dll not found" (not exactly the most useful error message because it gives the impression that the DLL can't be found, when its really the import library which can't be found.)

With languages like PowerBasic, you don't need to build import libraries. It's smart enough to know how to link the program correctly with just the function declaration. With FreeBasic, if you want to use custom 3rd party DLLs you have to go through the exercise of creating an import library using the GNU tools. Now, if you're a C/C++ programmer, you're familiar with import libraries. But for a lot of BASIC programmers, particularly ones who are used to working with PowerBasic or Visual Basic, the idea of dropping to the command prompt to build and link against import libraries is not something they're familiar with. And the fact that because it uses MinGW, it's not compatible with the export libraries created by Visual C++ or Borland C++ means that third-party library authors either have to provide the instructions on how to do all this, or go through the exercise of doing it themselves.

Most importantly, it's a level of additional complexity that doesn't need to be there aside from the fact that they want to reuse the GNU linker rather than implement their own that's integrated into the build process. It makes things easier for them on the cross-platform side of things, but it makes it unnecessarily harder for Windows programmers who want to migrate from languages like Visual Basic.
Mike Stefanik
sockettools.com

Marco Pontello

Quote from: Mike Stefanik on July 20, 2008, 07:54:19 PM
Try doing that with a third-party DLL for which you have no export library (no .a or .lib file), just the DLL itself, create a definition for it and try to compile the program.

That's exactly what I have done. For example for my TrIDLib library.
The library itself is coded in PowerBASIC (at the moment). But I have written a quick sample for using it from FreeBASIC, without having to do anything beside declaring it, as usual.

I may be missing something, off course.

Bye!

James C. Fuller

From The FreeBasic Help File:

James



'' create a function pointer, arguments must be the same
'' as in the original function

Dim AddNumbers As Function ( ByVal operand1 As Integer, ByVal operand2 As Integer ) As Integer

Dim hndl As Any Ptr

hndl=DyLibLoad("mydll.dll")

'' find the procedure address (case matters!)
AddNumbers = DyLibSymbol( hndl, "AddNumbers" )

'' then call it..
Print "1 + 2 ="; AddNumbers( 1, 2 )

DyLibFree hndl

Sleep



Marco Pontello

#7
On my above mentioned demo of using TrIDLib, I have a simple declaration on the .BI file, using #INCLIB & EXTERN, like:


...

#INCLIB "TrIDLib"

EXTERN "Windows-MS"

  DECLARE FUNCTION TrID_LoadDefsPack ALIAS "TrID_LoadDefsPack" (BYVAL szPath AS ZSTRING PTR) AS LONG

  ...

END EXTERN


And then using the DLL's function as usual:


szBuf = ""
ret = TrID_LoadDefsPack(szBuf) ' load the definitions package (TrIDDefs.TRD) from current path
         

I would think that the EXTERN "Windows-MS" take care of all the relevant details, effortlessy.

Mike Stefanik

I'd be interested to know what version of FreeBasic you're using. My test involved the FTP library in my company's SocketTools product. Here's the test code I wrote, which just calls the library's initialization function:


' test.bas
dim nKey as integer

declare function FtpInitialize lib "csftpav6.dll" alias "FtpInitializeA" ( _
        byval dwRuntimeKey as zstring ptr, _
        byval dwReserved as uinteger _
        ) as integer

if FtpInitialize(0, 0) <> 0 then
    print "Library initialization successful"
else
    print "Unable to initialize library"
end if

nKey = GetKey()


Based on what you wrote, I also tried:


' test.bas
dim nKey as integer

#inclib "csftpav6"

extern "Windows-MS"

declare function FtpInitialize alias "FtpInitializeA" ( _
        byval dwRuntimeKey as zstring ptr, _
        byval dwReserved as uinteger _
        ) as integer

end extern

if FtpInitialize(0, 0) <> 0 then
    print "Library initialization successful"
else
    print "Unable to initialize library"
end if

nKey = GetKey()


Here's the version that I'm using, which I understand to be the lastest version that's available:


C:\Program Files\FreeBASIC>fbc -version
FreeBASIC Compiler - Version 0.18.5 (04-17-2008) for win32 (target:win32)
Copyright (C) 2004-2008 The FreeBASIC development team.
Configured as standalone


Here's what happens when I try to compile it:


C:\Program Files\FreeBASIC>fbc test.bas
C:\PROGRA~1\FREEBA~1\bin\win32\ld.exe: cannot find -lcsftpav6.dll


The 'ld.exe' there is the GNU linker that's part of the MinGW distribution. It's looking for an import library named libcsftpav6.dll.a and can't find it, and returns an error. Now, perhaps earlier versions of FreeBasic didn't work this way, but the current release of FreeBasic definitely seems to depend on an older version of the GNU linker.
Mike Stefanik
sockettools.com

Marco Pontello

Same version as you:
C:\FreeBASIC>fbc -version
FreeBASIC Compiler - Version 0.18.5 (04-17-2008) for win32 (target:win32)
Copyright (C) 2004-2008 The FreeBASIC development team.
Configured as standalone

Mike Stefanik

Quote from: James C. Fuller on July 20, 2008, 08:20:58 PM
From The FreeBasic Help File...

That's a bit different than what I'm talking about. Dynamically loading the DLL is possible, but it means that you have to declare the function and then dynamically load each function that you want to call at runtime. It's a good thing to be able to do when you want to selectively load and unload DLLs, but in the vast majority of cases, an application will load a DLL when it executes and it remains loaded throughout the lifetime of the process.

Mike Stefanik
sockettools.com

Marco Pontello

As per above code, you may want to try using #INCLIB.

Mike Stefanik

#12
Thanks, I found out what the problem was. It only works if the DLL is in the same working directory as the source that you're compiling. For example, try moving tridlib.dll to c:\windows\system32 so that it's not in the same folder as the demo.bas source (but can still be loaded) and then try to compile it. You'll get:


C:\Program Files\FreeBASIC>fbc demo.bas
C:\PROGRA~1\FREEBA~1\bin\win32\ld.exe: cannot find -lTrIDLib


Apparently it does try to resolve those external function references, but it doesn't follow the standard Windows pathing rules for loading a DLL; if it doesn't find the DLL in the current directory, then it assumes that it's an external import library (which, of course, is a really poor assumption to make).

Edit: This isn't too bad when it's a single DLL, as in your case. With our SocketTools product, it would mean the developer would have to copy about 20 DLLs into their project directory. Of course, this is really more of an academic exercise on my part because we wouldn't likely find many folks using a $395 product with a beta release of a freeware compiler. But it's interesting nonetheless.
Mike Stefanik
sockettools.com

Marco Pontello

Quote from: Mike StefanikApparently it does try to resolve those external function references, but it doesn't follow the standard Windows pathing rules for loading a DLL; if it doesn't find the DLL in the current directory, then it assumes that it's an external import library (which, of course, is a really poor assumption to make).

OK, so that's not really a technical problem like it seemed (not sure about the verb here!) by your first analysis.
Don't seems a difficult thing to fix the "poor assumption" or to work around either.

Eros Olmi

Mike,

your signature link is not correct.

Eros
thinBasic Script Interpreter - www.thinbasic.com | www.thinbasic.com/community
Win7Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB