7

我用一个名为“render()”的函数创建了一个 DLL,我想将它动态加载到我的应用程序中,但 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;
}

我的目标是使用统一的 API 通过自己的 .DLL 制作一个支持 D3D 和 OpenGL 的 3D 引擎。我查看了记事本中的 .dll 并且有一个字符串“render”。

4

2 回答 2

12

您导出的函数被视为 C++ 函数(因为 *.cpp 文件扩展名),因此 C++名称修饰用于修饰导出的函数名称。如果您使用 Microsoft 的Dependency Walker工具检查您创建的 DLL,您将看到函数的全名。

您可以在导入代码中使用该修饰名称,也可以强制编译器以 C 样式导出函数,即以当前导入代码所期望的未修饰形式。

extern "C"您可以通过添加到您的函数签名来告诉编译器这样做。像这样的东西:

extern "C" D3D_API_API void render();

现在您的导入代码应该可以正常工作了。

于 2010-04-09T13:09:04.150 回答
0

正如对答案的评论所说:

使用 'extern "C"' 将删除任何 C++ 名称重整,但仍会留下 C 名称重整。为了导出纯名称,您应该使用 .DEF 文件查看。请参阅 blogs.msdn.microsoft.com/oldnewthing/20120525-00/?p=7533

您需要在项目中添加一个扩展名为 .DEF 的新文件,其内容类似于:

LIBRARY      "MyRenderLib"

EXPORTS
render

然后在您的 DLL 标头中,您不使用 __declspec(dllexport),而只使用 extern "C"

extern "C" void render();
于 2020-03-21T12:59:31.557 回答