[FFmpeg-devel] Fix libssh static linkage on Windows

Matt Oliver protogonoi at gmail.com
Mon Feb 10 15:35:03 CET 2014

On 11 February 2014 00:39, Michael Niedermayer <michaelni at gmx.at> wrote:

> On Thu, Feb 06, 2014 at 12:13:35PM +1100, Matt Oliver wrote:
> > On 6 February 2014 05:53, Reimar Döffinger <Reimar.Doeffinger at gmx.de>
> wrote:
> >
> > > On Thu, Feb 06, 2014 at 01:21:34AM +1100, Matt Oliver wrote:
> > > > On windows there are 2 ways to link to a function found in an
> external
> > > > shared library (.dll on windows). The first is to generate an export
> > > > library with your shared dll. This export library looks just like a
> > > static
> > > > lib but all the functions found in it point out to the external dll.
> The
> > > > second method is to declare each function as dllimport. This bypasses
> > > > needing to link to the export lib by explicitly stating its from a
> dll in
> > > > the code.
> > > >
> > > > dllimport is placed in front of any function or data declarations in
> code
> > > > to specify that they are found in an external .dll (.so shared
> library on
> > > > linux). If a function is declared as dllimport then the linker will
> only
> > > > look for that function in an external dll even if that function has
> been
> > > > provided with a static library. So linking will always fail if using
> a
> > > > static library to provide a function as the linker will only allow
> for an
> > > > external shared function.
> > >
> > > Are you sure about that? Because that is not my experience.
> > > As long as you use dllexport for the corresponding functions while
> > > compiling the static lib I believe it should work just fine.
> > > Note that you like this risk that libavformat ends up exporting
> > > the libssh functions, so it's not exactly such a great idea,
> > > but the underlying issue should be using dllimport where you use
> > > the function but not using dllexport where you defined it.
> > > Also, to quote Microsoft:
> > > > dllexport of a function exposes the function with its decorated name.
> > > For C++ functions, this includes name mangling. For C functions or
> > > functions that are declared as extern "C", this includes
> platform-specific
> > > decoration that's based on the calling convention. If you don't want
> name
> > > decoration, use a .def file (EXPORTS keyword).
> > >
> > > So it's basically a name mangling issue (for C I believe it's just
> > > that a _ is prepended).
> > > It also hints that just using a .def file and none of this
> > > dllimport/dllexport
> > > stuff would avoid the issue as well.
> > > _______________________________________________
> > > ffmpeg-devel mailing list
> > > ffmpeg-devel at ffmpeg.org
> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > >
> >
> > I probably shouldn't send emails at 2am after a late night as my last one
> > was a bit off. Your right in that dllimport is just a name mangling thing
> > that works providing you compiled the original static lib with dllexport.
> > Having dllimport means that it will only link with static libs compiled
> > using LIBSSH_EXPORTS (dllexport) as opposed to the more obvious
> > LIBSSH_STATIC. However building a static with that define requires the
> > linking program to also use that define. That is the reason for the patch
> > as with the define you can link against a static lib without exports
> while
> > also being able to link against a shared lib that does use exports.
> >
> > Given that the shared lib project provided by the libssh project defines
> > LIBSSH_STATIC then any static lib using the default libssh builds wont be
> > compatible with ffmpeg due to the conflicting use of dllexport. But by
> > adding the patch then not only will standard libssh static builds work
> but
> > the default shared builds will still work as well.
> is LIBSSH_STATIC officially defined to be safe to be defined for
> dynamic linking ? (it does not matter if its now with your installed
> libssh on your box)
> if yes please point me to the documentation
> if its defined not to be safe then this requires some #if id guess
> if its undefined then i think its best if you contact the libssh
> developers and ask so it gets clarified (in their docs) if
> unconditional use of LIBSSH_STATIC is how its supposed to be used.
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> I have often repented speaking, but never of holding my tongue.
> -- Xenocrates
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
is LIBSSH_STATIC officially defined to be safe to be defined for
> dynamic linking ?

Officially according to microsoft it is safe as any code in a shared dll on
windows needs to have exports defined that specify what functions/data
entry points are used in the dll. This is traditionally done using a module
exports .def file which does not need dllimport (although can still use
it). As per the Microsoft documentation:

"Microsoft introduced *__export* in the 16-bit compiler version of Visual
C++ to allow the compiler to generate the export names automatically and
place them in a .LIB file. This .LIB file could then be used just like a
static .LIB to link with a DLL.

Microsoft added *__declspec(dllexport)* to continue this convenience. Its
purpose is to add the export directive to the object file so you don't need
a .DEF file."

So with dllexport you can still officially link with the lib the same as
normal (or the same as a static lib) as dllexport is just the update of
export which was used before dllimport even existed (and is still used
today in .DEF files and .DEF files dont need dllimport). That said
microsoft still recommends using dllimport as it makes things easier for
the compiler by explicitly avoiding an indirection going from the .LIB ->
.DLL and go directly to the .DLL which potentially provide some
optimization advantages (although a modern compiler on O2 can optimize most
of these anyway - but thats not in the documentation).

libssh however has no stance on not using dllimport on a shared library and
there docs only state one or the other:

So unless libssh make a recommendation its kind of dealers choice. Theres
no way to know if a passed .LIB is for a static or shared library
automatically (as the documentation states they are used the same) so you
can either ignore dllimport or the only other way to support dllimport and
static would require user input and then a preprocessor if/else.

More information about the ffmpeg-devel mailing list