Динамически использовать DLL из консольного приложения - PullRequest
2 голосов
/ 23 апреля 2020

Я пытаюсь создать библиотеку Lib.dll для динамического вызова из консольного приложения, но не могу найти функцию funci() Я хочу вызвать.

Lib.dll является результатом проект (консольное приложение, но с заданным типом конфигурации: .dll), созданный в Visual Studio 2019.

Lib.cpp - единственный файл в этом проекте, содержащий только код:

__declspec(dllexport) int funci() 
{
    return 50;
}

Я думаю, что экспортирую функцию правильно, так как я нашел ее с помощью DLL Export Viewer v1.66 ​​.

enter image description here

Однако я пытаюсь найти функцию через мое консольное приложение (.exe):

#include <windows.h>
#include <iostream>

typedef int(__cdecl* o_funci)(void);

o_funci funci;

int main()
{
    HINSTANCE hGetProcIDDLL = LoadLibraryA("C:\\Lib.dll");

    if (!hGetProcIDDLL) {
        std::cout << "could not load the dynamic library" << std::endl;
        return EXIT_FAILURE;
    }

    // resolve function address here
    funci = (o_funci) GetProcAddress(hGetProcIDDLL, "funci");
    if (!funci) {
        std::cout << "could not locate the function" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "funci() returned " << funci() << std::endl;

    FreeLibrary(hGetProcIDDLL);
}

Что-то происходит неправильно в GetProcAddress, но не знаю почему. Может кто-нибудь помочь объяснить, где я go не прав?

Вывод:

enter image description here

Я просматривал этот старый пост: Динамически загружать функцию из DLL


РЕДАКТИРОВАТЬ: РЕШЕНО СПАСИБО tenfour

Я использовал DependencyWalker.

Без extern "C" я мог видеть, что неокрашенный funci имел имя ?funci@@YGHXZ,

enter image description here

Итак funci = (o_funci)GetProcAddress(hGetProcIDDLL, "?funci@@YGHXZ"); работал.

С extern "C" у неокрашенного funci было название _funci@0 - немного чище.

enter image description here

Другое примечание; использование порядкового номера 0x0001 сработало в обоих случаях. Как это: funci = (o_funci)GetProcAddress(hGetProcIDDLL, (PCSTR)0x0001);

enter image description here

1 Ответ

5 голосов
/ 23 апреля 2020

Инструмент, который вы используете, показывает вам симпатичную версию имени экспорта. Его настоящее имя будет включать в себя искажение имени, что является сложной попыткой встроить информацию о вызове в имя экспорта.

У вас есть несколько опций, позволяющих работать с GetProcAddress:

  1. Используйте НАСТОЯЩЕЕ имя экспорта. Ваш инструмент, вероятно, имеет возможность увидеть неселесное имя (искаженное имя экспорта)
  2. Экспортировать функцию, используя файл определения модуля (* .def), где вы даже можете указать имя, которое будет экспортировано as
  3. Импорт по порядковому номеру вместо имени
  4. Обернуть функцию в extern "C" { ... }, которая будет использовать стиль именования C, что позволит избежать искажения имени.

Наиболее распространенным решением, вероятно, является № 4 с № 2 в качестве второй секунды.

...