【问题标题】:dll export function pointer (best way to provide exported function hooking)dll 导出函数指针(提供导出函数挂钩的最佳方式)
【发布时间】:2015-10-27 19:09:50
【问题描述】:

我正在尝试为要调用的函数导出函数指针。我所追求的是当 dll/exe 中的函数需要调用另一个库导出的函数时,它会获取函数指针并调用它。这样做的原因是我想提供一个挂钩机制,并且我认为函数指针将是最快和最简单的方法,因为我可以轻松地更改它们指向的内容是运行时。 所以我找到了这个Exporting a function pointer from dll,但我无法让它工作。每当我调用它来获取函数指针时,我都会收到一个错误,它无法找到入口点。所以错误不是函数指针正在工作,而是获取函数指针的函数不工作。我相信这是一个功能签名问题。这是一个例子:

颜色.h

#ifndef __COLORS
#define __COLORS

#ifdef  MYDLL_EXPORTS 
/*Enabled as "export" while compiling the dll project*/
#define DLLEXPORT __declspec(dllexport)  
#else
/*Enabled as "import" in the Client side for using already created dll file*/
#define DLLEXPORT __declspec(dllimport)  
#endif

#include <string>
#include <vector>
class Colors
{
private:
     std::string myColor;
     static DLLEXPORT std::vector<std::string> allColors;
public:
     Colors(){};
     Colors(std::string MyColor);
     virtual DLLEXPORT std::string getMyColor();
     virtual DLLEXPORT void addToColors(std::string color);
     std::vector<std::string> getAllColors();
};
typedef Colors* (*create)(std::string);

DLLEXPORT create createColors();

Colors* createColors2(std::string color);



#endif

颜色.cpp

#define MYDLL_EXPORTS
#include "Color.h"




std::vector<std::string> Colors::allColors;

Colors::Colors(std::string MyColor)
{
     this->myColor = MyColor;
     this->allColors.push_back(this->myColor);
}

std::vector<std::string> Colors::getAllColors()
{
     return this->allColors;
}

std::string Colors::getMyColor()
{
    return this->myColor;
}

Colors* createColors2(std::string color)
{
    return new Colors(color);

}

DLLEXPORT void Colors::addToColors(std::string color)
{
     this->allColors.push_back(color);
}

DLLEXPORT create createColors()
{
     return &createColors2;
}

main.cpp

#define MYDLL_EXPORTS

#include <iostream>
#include <Windows.h>
#include "Color.h"



int main()
{


    Colors red("red");
    Colors blue("blue");

    Colors* dlltest;

    //Define the function prototype
    typedef Colors* (*createNewColor)();

    BOOL freeResult, runTimeLinkSuccess = FALSE;
    HINSTANCE dllHandle = NULL;
    createNewColor dllCreateNewColor = NULL;

    //Load the dll and keep the handle to it
    dllHandle = LoadLibrary(L"libs/testerdll.dll");

    // If the handle is valid, try to get the function address. 
    if (NULL != dllHandle)
    {

        //Get pointer to our function using GetProcAddress:
        dllCreateNewColor = (createNewColor)GetProcAddress(dllHandle,"createNewColor");

        // If the function address is valid, call the function. 
        if (runTimeLinkSuccess = (NULL != dllCreateNewColor))
        {

            dlltest = dllCreateNewColor();
            std::cout << "Color of dll class: " << dlltest->getMyColor() << std::endl;
        }
        else
        {
            std::cout << "Failed to locate function" << std::endl;
        }

            //Free the library:
            //freeResult = FreeLibrary(dllHandle);
    }
    else
    {
         std::cout << "Failed to load library" << std::endl;
    }

    std::vector<std::string> colorslist = red.getAllColors();
    for (std::string color : colorslist)
    {
        std::cout << color << std::endl;
    }
    return 0;
}

Dll 项目 dllmain.cpp

// testerdll.cpp : Defines the exported functions for the DLL application.


#include "stdafx.h"


#include "Color.h"



__declspec(dllexport) Colors* createNewColor()
{
    create temp1 = createColors();  //seems to fail here

    return nullptr;
}

是的,我知道我有内存泄漏等问题。这只是复制问题的快速示例代码。

【问题讨论】:

  • 不需要DLLEXPORT 虚函数——它们已经通过虚表中的函数指针找到了:)
  • 不使用class DLLEXPORT Colors自找麻烦。
  • ben 和 Dieter 能否提供示例?我正在尝试学习 dll 文件

标签: c++ pointers dll


【解决方案1】:

要返回函数,你需要得到它的地址,然后返回

例如

__declspec(dllexport) create createNewColor()
{
    create temp1 = createColors;

    return temp1;
}

但是,这个系统(使用 std::string 作为返回类型,要求 .exe 和 .dll 使用相同的基于 DLL 的运行时库。

stackoverflow : passing reference to STL over function boundary

C++ 没有定义文件之间的调用约定。这意味着不同的编译器可能会稍微不同地设置 C++ 对象。微软通过 COM 的定义限制了这一点,但这仍然是一种可能性。

对于 Visual Studio,运行时实例之间也有单独的堆 (new / delete)。当您链接到动态库时,进程中的所有 dll 和 exe 共享此 DLL。但是它们都需要一起更新。

所以这个过程可以工作,但要小心:-

  1. 在二进制文件 (DLL/EXE) 之间共享 C++ 类型 - 无 ABI
  2. 在 DLL 中使用 new,在 EXE 中使用 delete。 (不同的堆)。

STL 对象也存在问题,因为它们混合了标头实现(编译成二进制文件)和 DLL 实现(编译成 C++ 运行时)。

【讨论】:

  • 好的,谢谢它的工作。有没有更好的方法来实现函数挂钩 api?程序作为一个整体想要加载 dll 的/插件,如果其中一个需要挂钩主 exe 上的特定函数,以便将来来自其他插件的调用执行其中的函数(挂钩函数),是否有一个很好的正确方法去做?我只是认为这将是通过函数指针的最佳方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 2021-07-04
  • 2015-03-19
相关资源
最近更新 更多