(How) can a dll call a function that is implemented in its loading program?

0

Usually we load a dll on windows and call it's functions which is marked as __declspec(dllexport), but can I call a function which is implemented in the loaded program from a dll?

Firstly speaking this can be done on Linux, check the question I asked earlier.

I wrote a test program to test this: CMakeList.txt (sorry I'm new to Windows programming and don't know how to use visual studio):

cmake_minimum_required(VERSION 3.16)
project(untitled4)

set(CMAKE_CXX_STANDARD 17)

add_library(lib1 SHARED lib1.cpp)

add_executable(untitled4 main.cpp)

main.cpp

#include "iostream"
#include "windows.h"
extern "C" {
  // this is the function I want to get called from dll
__declspec(dllexport)
float get_e() {
  return 2.71;
}
}
int main() {
  auto *handler = LoadLibrary("lib1.dll");
  if (!handler) {
    std::cerr << ERROR_DELAY_LOAD_FAILED << std::endl;
    exit(1);
  }
  auto p = (float (*)()) GetProcAddress(handler, "get_pi");
  std::cout << p() << std::endl;
}

lib1.cpp:

#include "iostream"
extern "C" {
  // implemented in main.cpp
__declspec(dllimport)
float get_e();

__declspec(dllexport)
float get_pi() {
  std::cout << get_e() << std::endl; // comment this line will compile, just like the normal case
  return 3.14;
}
}

The compile will fail when building lib1:

NMAKE : fatal error U1077: '"C:\Program Files\JetBrains\CLion 2020.1.1\bin\cmake\win\bin\cmake.exe"' : return code '0xffffffff'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\bin\HostX86\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\bin\HostX86\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\bin\HostX86\x64\nmake.exe"' : return code '0x2'
LINK Pass 1: command "C:\PROGRA~2\MICROS~2\2019\BUILDT~1\VC\Tools\MSVC\1427~1.291\bin\Hostx86\x64\link.exe /nologo @CMakeFiles\lib1.dir\objects1.rsp /out:lib1.dll /implib:lib1.lib /pdb:C:\Users\derwe\CLionProjects\untitled\cmake-build-debug\lib1.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\lib1.dir/intermediate.manifest CMakeFiles\lib1.dir/manifest.res" failed (exit code 1120) with the following output:
   Creating library lib1.lib and object lib1.exp
lib1.cpp.obj : error LNK2019: unresolved external symbol __imp_get_e referenced in function get_pi
lib1.dll : fatal error LNK1120: 1 unresolved externals
Stop.

So can I do this on windows? That is to call a function in main from a dll?

P.S. Ideas of adding a registry function in dll and pass get_e through it is thanks but cannot be considered in my real case.

c++
windows
dll
dllimport
asked on Stack Overflow Dec 1, 2020 by psionic12

1 Answer

2

Since you are using late binding for your .dll, you might do the same thing for function defined in the executable. Just call GetProcAddress in the same way, using this process handle (as it is already in the address space). Here is some (pseudo) code:

auto proc = GetModuleHandle(nullptr);
auto get_e = reinterpret_cast<float (*) ()>(GetProcAddress(proc, "get_e"));
answered on Stack Overflow Dec 1, 2020 by SergeyA • edited Dec 1, 2020 by Remy Lebeau

User contributions licensed under CC BY-SA 3.0