GetProcAddress не может найти мои функции

Я создал библиотеку DLL с функцией render() и хочу динамически загрузить ее в свое приложение, но GetProcAddress не может ее найти. Вот DLL .h:

#ifdef D3D_API_EXPORTS
#define D3D_API_API __declspec(dllexport)
#else
#define D3D_API_API __declspec(dllimport)
#endif

D3D_API_API void render();

А вот и DLL .cpp:

#include "stdafx.h"
#include "D3D_API.h"
#include <iostream>

D3D_API_API void render()
{
    std::cout << "method called." << std::endl;
}

Вот приложение, которое пытается использовать эту функцию:

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

int _tmain(int argc, _TCHAR* argv[])
{
    HINSTANCE myDLL = LoadLibrary( L"D3D_API.dll" );

    if (myDLL == NULL) {
        std::cerr << "Loading of D3D_API.dll failed!" << std::endl;
    }

    typedef void (WINAPI *render_t)();

    render_t render = (render_t)GetProcAddress( myDLL, "render" );

    if (render == NULL) {
        std::cerr << "render() not found in .dll!" << std::endl;
    }
    return 0;
}

Моя цель - создать 3D-движок, который поддерживает D3D и OpenGL через свои собственные.DLL, используя унифицированный API. Я посмотрел на.dll в блокноте и там была строка "render".

1 ответ

Решение

Экспортируемая функция обрабатывается как функция C++ (из-за расширения файла *.cpp), поэтому для украшения имени экспортируемой функции используется искажение имени в C++. Если вы используете инструмент Dependency Walker от Microsoft для проверки созданной вами DLL, вы увидите полное имя функции.

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

Вы можете сказать компилятору сделать это, добавив extern "C" к вашей функции подписи. Что-то вроде этого:

extern "C" D3D_API_API void render();

Теперь ваш код импорта должен работать как ожидается.

Как говорится в комментарии к ответу:

использование extern "C" удалит любое искажение имени C++, но все же оставит искажение имени C. Чтобы экспортировать простые имена, вы должны использовать файл.DEF. См. http://blogs.msdn.microsoft.com/oldnewthing/20120525-00/?p=7533.

Вам необходимо добавить в проект новый файл с расширением.DEF, примерно такого же содержания:

LIBRARY      "MyRenderLib"

EXPORTS
render

Тогда в заголовке вашей DLL вы не используете __declspec(dllexport), а только extern "C"

extern "C" void render();
Другие вопросы по тегам