我需要有关LNK2019解决方法的建议

I need advice about a LNK2019 workaround

本文关键字:方法 解决 LNK2019      更新时间:2023-10-16

正如先前在此处讨论的那样,我正在尝试找到LNK2019问题的解决方法,该问题在构建利用C 模板的静态库时会出现,并将源与标头分开以保持来自其他项目的私人代码。我相信我几乎得出了结论(对于我的特定情况),但是我不确定这是否是正确/最好的方法,并且想知道是否有人有任何建议,改进/评论添加?

目标是进行某种类型检查,以查看模板的签名是否与目标原型函数的签名相匹配,进行一些私人处理,并返回是否成功。请注意,我已从上述链接中的解决方案的先前版本中删除了SdkHookMgr.hSdkHookMgr.cpp,并将所有内容汇回了 SdkLib.h SdkLib.cpp ,进入静态课程以稍微清晰。

sdklib.h:

#include <typeinfo>
#ifdef MY_EXPORTS
#   define MYDECL __declspec(dllexport)
#else
#   define MYDECL
#endif
// Prototypes
typedef HMODULE (WINAPI *HookLoadLibraryA)( LPCSTR lpFileName );
//...
class CHook;
class CHookManager;

MYDECL BOOL WINAPI ValidateHook( CHook *hook );
class CHook
{
public:
    CHook() : m_type(NULL), m_target(NULL), m_result(FALSE) {};
    CHook( const char *type, PVOID target ) : m_type(type), m_target(target) {
        m_result = ValidateHook(this);
    };
    const char *m_type;
    PVOID m_target;
    BOOL m_result;
};
class CHookManager
{
public:
    template <typename HookFunction> static BOOL Hook(HookFunction target)
    {
        const type_info& type = typeid(HookFunction);
        CHook *hook = new CHook( type.name(), target );
        return hook->m_result;
    }
};

sdklib.cpp:

#include <SdkLib.h>
IDXDECL BOOL WINAPI ValidateHook( CHook *hook )
{
    // Do type checking, private processing, etc here...
    return TRUE;
}

demodll.cpp:

#include <SdkLib.h>
HMODULE WINAPI Hooked_LoadLibraryA( LPCSTR lpFileName )
{
    DebugBreak();
}
// The function that starts the rollercoaster.
// - Syntax: Hook< prototype >( target )
if!(CHookManager::Hook<HookLoadLibraryA>(Hooked_LoadLibraryA))
    cout << "Failed to create hook for LoadLibraryA!" << endl;

您可能会发现typeid的结果在DLL和主程序之间不一致。(例如,请参阅不同DLL的TypeID结果。)

由于您可能的挂钩列表有限,因此使我的超载功能比模板更好。然后,您将没有DLL问题,并且在编译时将检查每个挂钩的有效性。这是我想的那种事情的例子;显然,实际上,您将其分为单独的定义和声明,而定义则存在于DLL中,因此所有这些都已干净地分开。

class CHookManager {
public:
    BOOL Hook(HookLoadLibraryA hook) {
        assert(sizeof hook<=sizeof(uintptr_t));
        return ValidateHook((uintptr_t)hook,"LoadLibraryA");
    }
    BOOL Hook(HookLoadLibraryW hook) {
        assert(sizeof hook<=sizeof(uintptr_t));
        return ValidateHook((uintptr_t)hook,"LoadLibraryW");
    }
};

(请注意,这显示出这种方法的一个缺点 - 您只能每个功能签名。>

(如果有的话,您可能想用编译时间断言代替。)

ValidateHook将使用strcmp来找出挂钩的钩子。一旦确定了它是哪个挂钩,它将将uintptr_t施加到适当的功能指针类型。它知道该指针最初是该挂钩的正确类型的,因为您使用的是C 过载机制来完成所有操作。(或者,对于所有钩类型,您可以说出一个枚举,而不是通过字符串传递 - 取决于您。关键部分是您对所传递的值有完全控制,因此DLL和调用代码肯定使用匹配值。)

此代码生成有点累人,但是如果您已经有Typedef名称的列表,则可以在选择的编辑器中使用正则表达式搜索和替换或键盘宏创建相应的代码。或者,您可以使用所谓的" X-MaCro"之类的东西来自动化整个事物的产生。