2

We have a project which is an executable, which loads DLL files at run time as plugins.

We're trying to make a new plug in which has many library dependencies, and some of those dependencies are the same library but different versions that other plugins link to.

Because the libraries are depended on by different plugins at different versions, I would like to statically link/build any dependencies into the new plugin - that way they can't conflict with the old plugin dependencies. As far as I know, nothing in the dependencies of the plugin need to be exported, they're just used by the plugin.

Is it possible to do this?

I've tried building all the static libs in visual studio as static libraries with the runtime set to Multithreaded DLL with the /MD flag, but when I try to build dynamiclibB.dll, I get linker errors. If I set dynamiclibB to build as a static library, it doesn't have the linker errors.

I haven't tried linking newplugin.dll to the static library version of dynamiclibB yet, but I think I have exactly the same situation, so I see no reason why it would work there where it doesn't one level down.

I don't want to build dynamiclibB as a static library anyway, as it would be good to be able to update newplugin.dll without including dynamiclibB.dll if it hasn't been changed, as in, to decouple the update process. This line of reasoning would suggest that I should have .dlls for everything, but the conflicts of versions is what worries me, I think.

I cannot build the plugins as static libraries as they need to be loaded at run time.

Absolutely everything is being built in release mode for now, to avoid that complication.

What am I missing?

An attempt at a diagram that might help understand the situation:

            program.exe
                |
         ________________
        |                |
  oldplugin.dll      newplugin.dll
        |                |
 dynamiclibA.dll     dynamiclibB.dll
                         |
            _________________________
           |             |           |
     staticlibA.lib   slibC.lib    slibD.lib   

Update: Providing some more information now that I know what's happening, and know that more specific details are actually relevant. So library A, represented by dynamiclibA and staticlibA was zlib. The library we were compiling (dynamiclibB) for use in the newplugin was PoDoFo. The error messages we got were:

Error   19  error LNK2001: unresolved external symbol
_deflateInit_   E:\Work\podofo_bin\src\PdfFiltersPrivate.obj    podofo_shared Error 20  error LNK2001: unresolved external symbol
_inflateEnd E:\Work\podofo_bin\src\PdfFiltersPrivate.obj    podofo_shared Error 21  error LNK2001: unresolved external symbol
_inflateEnd E:\Work\podofo_bin\src\libpng16.lib(pngread.obj)    podofo_shared Error 22  error LNK2001: unresolved external symbol
_deflate    E:\Work\podofo_bin\src\PdfFiltersPrivate.obj    podofo_shared Error 23  error LNK2001: unresolved external symbol
_deflate    E:\Work\podofo_bin\src\libpng16.lib(pngwutil.obj)   podofo_shared Error 24  error LNK2001: unresolved external symbol
_deflateEnd E:\Work\podofo_bin\src\PdfFiltersPrivate.obj    podofo_shared Error 25  error LNK2001: unresolved external symbol
_deflateEnd E:\Work\podofo_bin\src\libpng16.lib(pngwrite.obj)   podofo_shared Error 26  error LNK2001: unresolved external symbol
_inflateInit_   E:\Work\podofo_bin\src\PdfFiltersPrivate.obj    podofo_shared Error 27  error LNK2001: unresolved external symbol
_inflateInit_   E:\Work\podofo_bin\src\libpng16.lib(pngrutil.obj)   podofo_shared Error 28  error LNK2001: unresolved external symbol
_inflate    E:\Work\podofo_bin\src\PdfFiltersPrivate.obj    podofo_shared Error 29  error LNK2001: unresolved external symbol
_inflate    E:\Work\podofo_bin\src\libpng16.lib(pngrutil.obj)   podofo_shared

Putting the rest in an answer.

Lynden Shields
  • 1,062
  • 1
  • 10
  • 27
  • Questions: "some of those dependencies are the same library but different versions that other plugins link to" - this means that old/newplugin.dll are just different versions, right? Does that also apply to dynamiclibA/B.dll? If so, can I assume that the old+A and new+B pairs were built with different versions of MSVC? Also, what linker errors are you getting for dynamiclibB? – frasnian Jan 22 '15 at 12:44
  • Old and new plugins are completely unrelated plugins that just happen to have the same dependencies eventually. – Lynden Shields Jan 22 '15 at 12:47
  • Everything is msvc10 – Lynden Shields Jan 22 '15 at 12:47
  • DynamiclibA and staticlibA are the same library at different versions. On phone at the moment so can't get the errors until tomorrow, but they go away when I switch the output of b to .Lib, even if I don't change the run time (everything /MD) – Lynden Shields Jan 22 '15 at 12:50
  • I bookmarked your question, so whenever for the link errors - SO will ping me. Kudos on the ASCII-art diagram, BTW. – frasnian Jan 22 '15 at 12:54
  • Thanks, but I plagiarised it from another similar question :p – Lynden Shields Jan 22 '15 at 12:55
  • Shoulders of giants and all that – Lynden Shields Jan 22 '15 at 12:56
  • I can give a little more info from memory, there are actually multiple libraries that fit the situation represented by library a, but the one in question right now is zlib. The linker errors are, iirc, just that all the exported functions from zlib can't be found while linking from dynamic library b. As I said, the link errors disappear when building b as a static library, despite still having /MD. My understanding was that dll versus static Lib didn't really change anything except where the binary is actually stored, when the runtime is kept the same. I must be wrong, but what's the truth? – Lynden Shields Jan 22 '15 at 13:27

1 Answers1

0

In my question, slibc.lib was libpng. Libpng also requires zlib, but it builds it from source inside its solution. We were able to use the output of that project in the way we desired, as in, zlib.lib built with /MD flag, without linking errors.

We've also managed to work out why this problem occurred: another stackoverflow question was very relevant: https://stackoverflow.com/a/6559315/78823

Turns out that zlib has a #define ZLIB_WINAPI which defined the call convention to be STDCALL, which I don't understand, but it caused the linker errors. The other answer suggests to remove the define, and I suppose that's what libpng did with its zlib project.

I'm guessing that the reason why the linker errors only occurred when building the .dll and disappeared when building the .lib is because (correct me if I'm wrong, I don't fully understand this), build a .lib doesn't actually do the linking to the required functions, so would have been just passing on the linker errors to the next level up; I think we would have seen the same errors (but in different objs/projects perhaps) when compiling newplugin.dll, but we didn't get far enough to check that before we tried other things.

Community
  • 1
  • 1
Lynden Shields
  • 1,062
  • 1
  • 10
  • 27
  • Your guess is correct. A .lib is scarcely more complex than a zip file of the constituent .obj files (it does also have a global directory mapping named exports to the name of the .obj that contains it). The .lib doesn't mess with externals its constituent code depends on, and since the linker may choose to use only a subset of the ,obj members, the set of required symbols can vary. – Ben Voigt Jan 23 '15 at 00:01
  • 1
    Did you actually solve the problem, and managed to link libA statically into your libB.dll? Very curious, because I'd like to do the same – J.P. Jun 10 '20 at 13:28