Wow, good job. You're really moving forward with this.
I noticed in the diff for your commit on master of the fork of miniupnp:
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;DEBUG;%(PreprocessorDefinitions);</PreprocessorDefinitions>
It seems the MINIUPNP_STATICLIB define was removed from the pre-processor definitions, and then added to the source file.
This is confusing, since I would expect that to not be defined for a DLL build.
I checked back to the prior commit.
Checking the file: miniupnpc/msvc/miniupnpc.vcxproj, I noticed there were 4 project configurations: Debug Dll, Debug, Release Dll, and Release. As expected, the Debug and Release configurations have their ConfigurationType set to StaticLibrary, and have a PreprocessorDefinitions list including MINIUPNP_STATICLIB.
It looks like the project already has configurations for both DLL and static library builds.
Perhaps the original problem was simply a matter of changing which configuration got built?
(And of course the toolset upgrade)
The project file changes for libnatpmp look more extensive. Looked like the solution file was for an older version, and the upgrade amounted to basically rewriting the whole file, and adding all new project files. Curiously, I noticed the project file was split, with DLL builds in one project file, and static library builds in the other file, rather than having all 4 configurations in one project file.
It looks like the static configuration project file already has the necessary NATPMP_STATICLIB preprocessor macro defined. I don't think it needs to be added to the source file as well.
Looks like the new project files would be useful to contribute back to the original author. I might suggest combining all 4 configurations into one project file though.
The #define ssize_t SSIZE_T looks relevant, and may be worth contributing back. I don't know enough about it to really comment on it.
I'd be curious to know how the #define interacts with older versions of the Windows kits.
From my cursory reading, it sounds like ssize_t is a signed version of size_t, used when a negative return value is used as a sentinel value, for what would otherwise be a positive size_t type value. It's part of Posix, but not part of the C/C++ standards.
Turns out, if I define the macros in both libnatpmp/miniupnp and NetHelper project settings, it compiles properly without adding the define directly in the source code.
Ahh, that makes sense. The header files need to be processed both in the context of the library, while the library is being compiled, and in the context of the main program using the library, when the main program is being compiled.
For a DLL, the #defines used for declarations in the header files need to be different between the library and the main project. For the library itself, it needs to export symbols from the header files. For the main project, it needs to import symbols from the header files. That's typically controlled by having a default of import, so the project can use the header files without special configuration, but within the library itself, they compile with an extra define in the project settings to switch to export instead of import.
In libnatpmp, this is controlled by NATPMP_LIBSPEC, which is defined in natpmp_declspec.h:
(In miniupnp, the structure is equivalent, but using MINIUPNP_LIBSPEC instead, which is defined in miniupnpc_declspec.h).
#if defined(_WIN32) && !defined(NATPMP_STATICLIB)
/* for windows dll */
#ifdef NATPMP_EXPORTS
#define NATPMP_LIBSPEC __declspec(dllexport)
#else
#define NATPMP_LIBSPEC __declspec(dllimport)
#endif
#else
#if defined(__GNUC__) && __GNUC__ >= 4
/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */
#define NATPMP_LIBSPEC __attribute__ ((visibility ("default")))
#else
#define NATPMP_LIBSPEC
#endif
#endif
For a DLL build, when NATPMP_EXPORTS is defined, the headers will export the symbols, otherwise it defaults to importing the symbols. NATPMP_EXPORTS seems to be defined in build.bat for gcc builds, but curiously I don't see any references to it any any MSVC project files.
For static builds, when NATPMP_STATICLIB is defined, it instead builds a static library (for the library project), or tries to link to a static library (from the main project). There is no difference between import and export for a static library.
If you did not have NATPMP_STATICLIB defined in the main project, it would treat the header files as defining DLL imports. Hence the link errors when you're trying to link to a static version of the library.
Well, I'm glad you managed to figure that out.