在运行时实现存根函数并将其链接到库中的定义

问题描述

当我阅读有关使用共享库的文章时,我了解到标准 C 函数(如 printf)的定义是如何在运行时解析的。 我想以类似的方式在我的项目中实现功能。我可以有用于编译和链接阶段的函数的存根定义。函数的实际定义将出现在我将运行可执行文件的设备上的库中。

假设我有一个函数

#include<stdio.h>
#include"sum.h"
int main()
{
    int num = 10;
    int result = 0;
    result = sum(num);
    printf("Sum = %d\n",result);
    return 0;
}

我的 sum.h 看起来像:

#ifndef SUM_H
#define SUM_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef __EXPORT
#ifdef _USERDLL
#define __EXPORT __declspec(dllexport)
#else
#define __EXPORT __declspec(dllimport)
#endif // _USER_DLL
#endif // __EXPORT

__EXPORT int sum(int num);
}
#endif
#endif

在构建这个可执行文件时,我将使用 sum_stub.c 文件中的存根定义:

// sum_stub.c
#include<stdio.h>
#include"sum.h"
int sum(int num) {
    int res = 0;
    printf("Inside stubbed function. Result=%d\n",res);
    return res;
}

让使用上述文件构建的可执行文件为 get_sum.exe

计算 sum 的实际函数被编译为共享库,比如 sum.dll。

// sum.c that will be compiled to sum.dll
#include<stdio.h>
#include"sum.h"
int sum(int num) {
    int res = 0;
    int i=0;
    for (i=0; i<num; i++)
        res = res + i;
    return res;
}

现在,当我运行我的可执行文件 get_sum.exe 时,如何在运行时链接 sum.dll 以便使用正确的函数定义(在 sum.dll 中)而不是我在编译可执行文件时使用的存根函数定义? 我正在寻找一种在 Windows 目标机器上实现它的方法,即使用 MSVC 构建工具和 clang 编译器。

解决方法

您正在寻找的称为“延迟加载的 DLL”。 MSDN article on Linker support for delay-loaded DLLs 中提供了有关覆盖默认 DLL 加载代码的详细信息。