Topic: [SOLVED] libusb0.dll and Win32 catch-22

There is a catch-22 with libnfc and windows.

With Windows, the libusb0.dll only gets transferred to the system32 directory once a device has been detected and associated with the libusb0.sys etc. So you can't have libnfc.dll linked to libusb0.dll and expect it to work out of the box with, say a PCSC device, unless something else cause libusb0.dll to get installed.

So the windows build needs a cunning stub mapping of all the libusb functions so it can continue working without libusb0.dll being available.

Our solution was to use a static linking of libnfc in a standalone DLL that can be demand loaded to provided the libnfc functions once Windows has correctly configured a USB driver.

Re: [SOLVED] libusb0.dll and Win32 catch-22

Thanks for this report.
I don't use (understand) Windows at all so I can't see your kind of annoyance, but what can we do to prevent form your problem?

Do you have some patches to enhance libnfc ? Or maybe, some examples to show how to handle with this catch-22 ?

Romuald Conty

Re: [SOLVED] libusb0.dll and Win32 catch-22

I think this problem needs to be sorted out with the windows binary installation (Issue 21).

I suggest  a decision needs to be made how libnfc should be installed correctly on Windows and which directory it should live in (either windows\system32 or program files\common files.... ).

It should also be separate from libusb0 which is really a separate project and libnfc should not require it to be present due to the installation sequence outlined above.

I could build some stubs to the libusb functions used by libnfc and advise how to link them with the libnfc project.

Similarly, the MacOSX library should really be built as a framework shared library, eg "/Library/Frameworks/NFC.framework/...." and as a fat ppc/i386 binary.

I'm not a big fan of "/usr/local/lib" on MacOSX, we've had good success binding libusb as a static library in executables, it's really just a shim onto IOKit.

Last edited by snapdev (2010-05-03 10:43:52)

Re: [SOLVED] libusb0.dll and Win32 catch-22

snapdev wrote:

I think this problem needs to be sorted out with the windows binary installation (Issue 21).

Hmm, that's taboo ! tongue

snapdev wrote:

I suggest  a decision needs to be made how libnfc should be installed correctly on Windows

I said, that's taboo !.. Of course, I'm joking : the point is there is nobody to maintains libnfc under Windows :
Roel mainly use MacOS X (with a tricky installation ^^)
Romain uses FreeBSD, Ikelos uses Gentoo, FKooman uses Fedora (even I had started great Windows part: put CMake to build and package libnfc), for Adam, I don't know and finally I'm using Debian and derivated distros. So nobody daily use libnfc with Windows as OS ([troll] maybe that's related to that Windows is not daily usable... [/troll] ^^)

snapdev wrote:

and which directory it should live in (either windows\system32 or program files\common files.... ).
It should also be separate from libusb0 which is really a separate project and libnfc should not require it to be present due to the installation sequence outlined above.
I could build some stubs to the libusb functions used by libnfc and advise how to link them with the libnfc project.

Feel free to enhance Windows support ! ATM, trunk should (almost) works on Windows using CMake.
Technicals suggestions and problems exposure/solving is more than welcome. You also should create an issue to explain the problem and potential solving on http://code.google.com/p/libnfc/issues/entry

snapdev wrote:

Similarly, the MacOSX library should really be built as a framework shared library, eg "/Library/Frameworks/NFC.framework/...." and as a fat ppc/i386 binary.

I'm not a big fan of "/usr/local/lib" on MacOSX, we've had good success binding libusb as a static library in executables, it's really just a shim onto IOKit.

That could be an interesting talk. Could you open a second issue on this subject ?

Romuald Conty

Re: [SOLVED] libusb0.dll and Win32 catch-22

Watch this space! smile

Re: [SOLVED] libusb0.dll and Win32 catch-22

I have written a wrapper usb library which intercepts the libusb calls and demand loads the LIBUSB0.DLL.

I have written a Makefile which demonstrates building libnfc.dll on Windows with the freely downloadable Visual Studio 2008, and has DEF file, RC file containing version and manifest file.

COMMONOPTS=/W3 /MD /DNDEBUG /DWIN32 /D_WIN32_DCOM /D_WIN32_WINNT=0x500 /D_CRT_SECURE_NO_DEPRECATE /Zp8 /DNTDDI_VERSION=0x05000400    
NFCOPTS=/I..\include /I..\contrib\win32 /I..\contrib\win32\stdint /DDRIVER_PN531_USB_ENABLED /Iusb\include
NFCLIBOPTS=/Dnfc_EXPORTS /DPACKAGE_VERSION=\"1.3.4\"
CFLAGS=$(COMMONOPTS) /WX $(NFCOPTS)
CXXFLAGS=$(COMMONOPTS) /EHa $(NFCOPTS)
CC=cl.exe /nologo
CXX=$(CC)
CC_OUT_EXE=/Fe
CC_OUT_DLL=/LD /Fe
CC_OUT_OBJ=/Fo

LIBNFC_DLL=bin\libnfc.dll
NFC_LIST=bin\nfc-list.exe

LIBNFC_OBJ=    obj\nfc.obj            \
            obj\pn531_usb.obj    \
            obj\pn53x_usb.obj    \
            obj\usbstub.obj        \
            obj\pn53x.obj        \
            obj\mirror-subr.obj    

NFCLIST_OBJ=obj\nfc-list.obj    \
            obj\nfc-utils.obj

all: obj bin $(LIBNFC_DLL) $(NFC_LIST)

clean:
    for %d in ( $(LIBNFC_DLL) $(NFC_LIST) ) do if exist %d del %d
    for %d in ( $(LIBNFC_OBJ) $(NFCLIST_OBJ) ) do if exist %d del %d
    for %d in ( obj\nfc-list.res obj\libnfc.res ) do if exist %d del %d
    for %d in ( bin\libnfc.exp bin\libnfc.lib ) do if exist %d del %d
    if exist obj rmdir obj
    if exist bin rmdir bin

obj bin:
    mkdir $@

$(LIBNFC_DLL): $(LIBNFC_OBJ) win32\libnfc.def obj\libnfc.res
    $(CC)  $(CC_OUT_DLL)$@ $(LIBNFC_OBJ) obj\libnfc.res /link /DEF:win32\libnfc.def 
    if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;#2
    if exist $@.manifest del $@.manifest

$(NFC_LIST): $(NFCLIST_OBJ) $(LIBNFC_DLL) bin\libnfc.lib obj\nfc-list.res
    $(CC) $(CC_OUT_EXE)$@ $(NFCLIST_OBJ) bin\libnfc.lib obj\nfc-list.res
    if exist $@.manifest mt.exe -manifest $@.manifest  -outputresource:$@;#1
    if exist $@.manifest del $@.manifest

obj\nfc-list.obj: ..\examples\nfc-list.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(CFLAGS) ..\examples\nfc-list.c

obj\nfc-utils.obj: ..\examples\nfc-utils.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(CFLAGS) ..\examples\nfc-utils.c

obj\nfc.obj: ..\libnfc\nfc.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(NFCLIBOPTS) $(CFLAGS) ..\libnfc\nfc.c

obj\pn531_usb.obj: ..\libnfc\drivers\pn531_usb.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(NFCLIBOPTS) $(CFLAGS) ..\libnfc\drivers\pn531_usb.c

obj\pn53x_usb.obj: ..\libnfc\drivers\pn53x_usb.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(NFCLIBOPTS) $(CFLAGS) ..\libnfc\drivers\pn53x_usb.c

obj\pn53x.obj: ..\libnfc\chips\pn53x.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(NFCLIBOPTS) $(CFLAGS) ..\libnfc\chips\pn53x.c

obj\usbstub.obj: usb\src\usbstub.cpp
    $(CXX) /c $(CC_OUT_OBJ)$@ $(NFCLIBOPTS) $(CXXFLAGS) usb\src\usbstub.cpp

obj\mirror-subr.obj: ..\libnfc\mirror-subr.c
    $(CC) /c $(CC_OUT_OBJ)$@ $(NFCLIBOPTS) $(CFLAGS) ..\libnfc\mirror-subr.c

obj\libnfc.res: win32\libnfc.rc
    rc /r $(RCFLAGS) /fo$@ win32\libnfc.rc

obj\nfc-list.res: win32\nfc-list.rc
    rc /r $(RCFLAGS) /fo$@ win32\nfc-list.rc

I have written a MakeMSI script which will build an installer for Win32, and installs components as follows:

 Directory of c:\windows\system32

04/05/2010  02:33 p.m.            26,112 libnfc.dll

and

 Directory of C:\Program Files\libnfc\bin

04/05/2010  02:37 p.m.    <DIR>          .
04/05/2010  02:37 p.m.    <DIR>          ..
04/05/2010  02:34 p.m.            10,240 nfc-list.exe
               1 File(s)         10,240 bytes
               2 Dir(s)   7,976,374,272 bytes free

What happens now?

Re: [SOLVED] libusb0.dll and Win32 catch-22

I have created a package of files that will do the build and packaging for Windows. How do I submit it?

Interesting, I've found a number of places where the C code is being compiled as if it's C++, eg defining arrays of data prior to use in the middle of functions, also returning "NULL" as a bool type, when NULL is actually "(void *)0".

Regards,

snapdev

Last edited by snapdev (2010-05-05 05:36:02)

Re: [SOLVED] libusb0.dll and Win32 catch-22

snapdev wrote:

I have created a package of files that will do the build and packaging for Windows.

Great ! Why didn't you enhanced CMake instead of creating separate Makefile ? BTW, that could be interesting for Windows users.

snapdev wrote:

How do I submit it?

As previously said: Open an issue on libnfc development site, describe the problem, attach your patches.
To produce the patch file, it should be easier to use subversion.

snapdev wrote:

Interesting, I've found a number of places where the C code is being compiled as if it's C++, eg defining arrays of data prior to use in the middle of functions, also returning "NULL" as a bool type, when NULL is actually "(void *)0".

Open an issue on libnfc development site, describe the problem, attach your patches. tongue

Thanks for your help.

Romuald Conty

Re: [SOLVED] libusb0.dll and Win32 catch-22

I've had a look at the CMake stuff for windows and it looked more complicated than it needed to be.

Why name the DLL "nfc.dll" when the project is called "LIBNFC"? smile I know it's following the conventions,but for both project image and avoiding conflicts I think LIBNFC would look better. The LIBUSB-Win32 project happily names their module LIBUSB0.DLL.

Last edited by snapdev (2010-05-06 09:56:47)

Re: [SOLVED] libusb0.dll and Win32 catch-22

snapdev wrote:

I've had a look at the CMake stuff for windows and it looked more complicated than it needed to be.

What is more complicated than it needed to be ? We are interesting in simplying everything that could be !

snapdev wrote:

Why name the DLL "nfc.dll" when the project is called "LIBNFC"? smile

Totally agree, "libnfc0.dll" sounds good.

Romuald Conty

Re: [SOLVED] libusb0.dll and Win32 catch-22

The CMake step had 6 prereqs and 3 command line steps,

My approach had two preqs (Visual Studio and MakeMSI) and one build step "nmake install" to make an MSI.

With the DLL naming, with LIBUSB0 the digit comes from the major version prefix, just like Linux traditionally has the major version only in the soname. So following that convention, "libnfc.1.3.4" would become "LIBNFC1", where the version number in the name is really talking about the consistency of the binary API itself.

I posted up a ZIP which does the same as the CMake, eg makes "NFC.DLL" and MSI to install lib and includes in "C:\program files\libnfc-1.3.4" under "issue 21".

Also, regarding the consistency of API on windows, I strongly recommend using a DEF file to control the exports (as included in ZIP).

Re: [SOLVED] libusb0.dll and Win32 catch-22

How should the descision be made? For general acceptance the project needs consistent binary level interface, this includes API set, calling conventions and module naming.

So the three issues I see for Windows are

(a) module naming, a choice between (i) NFC.DLL, (ii) LIBNFC.DLL, and (iii) LIBNFC1.DLL, Windows DLLs don't traditionally put the version in the filename, the new "side-by-side" assemblies is supposed to be the way forward to solve DLL-hell.

(b) explicitly specifying the calling convention in the header files __cdecl or __stdcall rather than defaulting to whatever the compiler is currently set to. For a Windows DLL, the "correct" calling convention  for exports across DLLs is "__stdcall" as it at least a defined standard, "__cdecl" is a compiler dependant calling convention.

(c) using decorated or undecorated exports, for a project written in C, I personally prefer undecorated exports explicitly controlled by a DEF file to limit the exports, rather than __declspec(dllexport) in the code to define exports.

My vote would be "LIBNFC.DLL",  __stdcall and use DEF files with undecorated exports.

Re: [SOLVED] libusb0.dll and Win32 catch-22

snapdev wrote:

How should the descision be made?

Depending on the subject, the decision is usually taken using googlecode issue tracker or IRC : any volunter leave his point of view (usually with patches), quickly there is a kind a consensus and patches finally applied.

In this particular case, you are the only one at the moment that bring us patches for Windows part. So, if you can bring something more powerful for Windows users, you are more than welcome !

snapdev wrote:

My vote would be "LIBNFC.DLL",  __stdcall and use DEF files with undecorated exports.

My vote would be :
a) As windows users want... if there is no inconvenience for other platforms users.
b) As windows developers want... if there is no inconvenience for other platforms developers.
c) I prefer undecorated exports... because i like when the code is beautiful wink

Romuald Conty