0

I have a .lib library which provides APIs which have global variables like file/device handles, these APIs are going to be used by the application(.exe) by linking with .lib statically. The application does some initialization using APIs provided by .lib (like opening device/file etc) and loads the .dll during run time to perform writes and reads to the device/file using APIs provided by .lib. The problem is when I link the static library with both .exe and .dll they have different copies of libraries and the initialization done by the application is not retained when .dll is opened during run-time (since .dll and .exe seem to be working with their own copy of .lib). This problem is solved when I make .dll instead of static library and export all APIs and import them in .exe and .dll.

But I want to make the .exe standalone without any .dll dependencies except for run-time .dll .

Here is sample code for scenario

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\n", dllname);
        return 0;
    }

    functionname=(FNPTR)GetProcAddress((HMODULE)hLib, (LPCSTR)"dyn_main"); 

    if((functionname==NULL))
    {
        printf("unable to load test function %s\n", 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 (static library)

#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\n",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;
}

The command line for compiling with dynamic linking is

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

The output is:

main.exe
Var in main: 1
calling dyn_main:1
back to main:1

But when I make a static library and link with .exe and .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

The output is

main.exe
Var in main: 1
calling dyn_main:0
back to main:1

And in real scenario the program crashes as it is invalid device/file handle inside .dll.

Is there anyway to export APIs into .dll from .exe without linker giving unresolved symbol error and maintaining only one copy of static library used by .dll and .exe?

I have searched for the problem and I found this: Dynamic Loading of my DLL with Static Lib in Windows Environment

It says we cannot do this in windows environment. But I want to make sure before thinking of other alternatives.

  • simply make this functions (`test_func`..) part of exe and export it from exe. and import from dll – RbMm Aug 03 '18 at 09:16
  • This is clearly a design issue. From the question I can't understand why is the *.dll* needed when everything could be done from the *.exe*. Or the other way around, link everythink in the *.dll* (including initialization) and use the *.exe* only to call the funcs. Or the 3rd option (if you want to do half of the stuff from the *.exe* and the other from the *.dll* - although this makes the least sense), you should build the static lib as a dynamic one. – CristiFati Aug 08 '18 at 15:12

0 Answers0