windows - Deling af statisk bibliotek mellem .dll (runtime loading) og .exe

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et .lib bibliotek, der leverer API'er, der har globale variabler som fil/enhedshåndtag, vil disse API'er blive brugt af applikationen (.exe) ved at linke med .lib statisk. Programmet gør nogle initialisering ved hjælp af API'er, der leveres af .lib (som åbningsenhed/fil osv.) Og indlæser .dll i løbetid for at udføre skriver og læser til enheden/filen ved hjælp af API'er, der leveres af .lib. Problemet er, når jeg forbinder det statiske bibliotek med både .exe og .dll de har forskellige kopier af biblioteker, og initialiseringen udført af applikationen beholdes ikke, når .dll åbnes i løbetid (da .dll og .exe synes at arbejder med deres egen kopi af .lib). Dette problem er løst, når jeg laver .dll i stedet for statisk bibliotek og eksporterer alle API'er og importerer dem i .exe og .dll.


Men jeg vil gøre .exe standalone uden nogen .dll afhængigheder undtagen run-time. Dll.


Her er prøvekode for scenarie


main.c (.exe)


#include <stdio.h>
#include <windows.h>
#include "static\_lib.h"


typedef void (*FNPTR)(void);

FNPTR functionname;

int main(){
    HINSTANCE hLib;
    LPTSTR dllname = "dynamic.dll";

    hLib=LoadLibrary(dllname);

    if(hLib==NULL)
    {  
        printf("Unable to load dll \%s
", dllname);
        return 0;
    }

    functionname=(FNPTR)GetProcAddress((HMODULE)hLib, (LPCSTR)"dyn\_main"); 

    if((functionname==NULL))
    {
        printf("unable to load test function \%s
", dllname);
        FreeLibrary((HMODULE)hLib);
        return 0;
    }

    printf("Var in main: ");
    test\_func();

    printf("calling dyn\_main:");
    functionname();

    printf("back to main:");
    printvar();

    FreeLibrary((HMODULE)hLib);
    return 1;
}


static\_lib.c (statisk bibliotek)


#include <stdio.h>
#include <windows.h>
#include "static\_lib.h"


int var;                //can be file or device handle


int test\_func(){        //initializes the device 
    change\_var();           
    printvar();
    return 1;
}

void printvar(void){        //write/read device/file
    printf("\%d
",var);
    return;
}

void change\_var(void){   //opens device/file
    var = 1;
    return;
}


static\_lib.h


#ifndef \_STATIC\_LIB\_H\_
#define \_STATIC\_LIB\_H\_

#if defined (DLL\_EXPORT)
    #define DLL\_IMPORT\_EXPORT \_\_declspec(dllexport)
#else
    #define DLL\_IMPORT\_EXPORT \_\_declspec(dllimport)
#endif

DLL\_IMPORT\_EXPORT void change\_var(void);
DLL\_IMPORT\_EXPORT void printvar(void);
DLL\_IMPORT\_EXPORT int test\_func();

#endif


dynamic.c (.dll)


#include <stdio.h>
#include <windows.h>
#include "static\_lib.h"


\_\_declspec(dllexport) void dyn\_main(void){      
    printvar();                             //uses the device
    return;
}


Kommandolinjen til kompilering med dynamisk linking er


cl /c /nologo main.c dynamic.c
cl /c /nologo /DDLL\_EXPORT static\_lib.c
LINK /nologo /DLL  static\_lib.obj
LINK  /nologo /DLL dynamic.obj static\_lib.lib
LINK /nologo  main.obj static\_lib.lib


Udgangen er:


main.exe
Var in main: 1
calling dyn\_main:1
back to main:1


Men når jeg laver et statisk bibliotek og linker med .exe og .dll


cl /c /nologo main.c dynamic.c static\_lib.c
LIB static\_lib.obj
LINK  /nologo /DLL dynamic.obj static\_lib.lib
LINK /nologo  main.obj static\_lib.lib


Udgangen er


main.exe
Var in main: 1
calling dyn\_main:0
back to main:1


Og i reelt scenario bryder programmet, da det er ugyldigt enhed/filhåndtag inde i .dll.


Er der alligevel at eksportere API'er til .dll fra .exe uden linker, der giver uopløst symbolfejl og vedligeholder kun en kopi af statisk bibliotek, der bruges af .dll og .exe?


Jeg har søgt efter problemet, og jeg fandt dette: Dynamisk indlæsning af min DLL med Statisk Lib i Windows Miljø [9]


Det siger, at vi ikke kan gøre dette i Windows-miljø. Men jeg vil gerne være sikker på, før jeg tænker på andre alternativer.

Bedste reference