dll导出函数指针(提供导出函数挂钩的最佳方式)
dll export function pointer (best way to provide exported function hooking)
我正在尝试为要调用的函数导出函数指针。我所追求的是,当dll/exe中的函数需要调用另一个库导出的函数时,它会获得函数指针并调用它。原因是我想提供一种挂钩机制,我认为函数指针是最快、最简单的方法,因为我可以在运行时轻松地更改它们指向的内容。所以我发现了这个从dll导出函数指针,我无法让它工作。每当我调用它来获取函数指针时,我都会得到一个错误,即它找不到入口点。所以错误不在于函数指针在工作,而在于获取函数指针的函数不工作。我认为这是一个函数签名问题。这里有一个例子:
Colors.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
colors.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;
}
是的,我知道我有内存泄漏等。这只是一个复制问题的快速示例代码。
要返回函数,您需要获取它的地址,并返回
例如
__declspec(dllexport) create createNewColor()
{
create temp1 = createColors;
return temp1;
}
但是,这个系统(使用std::string作为返回类型)要求.exe和.dll使用相同的基于dll的运行库。
stackoverflow:通过函数边界传递对STL的引用
C++没有定义文件之间的调用约定。这意味着不同的编译器设置C++对象的方式可能略有不同。微软通过COM的定义限制了这一点,但这仍然是可能的。
同样对于visualstudio,运行时实例之间也有单独的堆(new
/delete
)。当您链接到动态库时,进程中的所有DLL和exe都共享此DLL。但它们都需要一起更新。
因此,这个过程可以工作,但要警惕:-
- 在二进制文件(DLL/EXE)之间共享C++类型-无ABI
- 在DLL中使用new,在EXE中使用delete。(不同的堆)
STL对象也是有问题的,因为它们是头实现(编译成二进制)和DLL实现(编译到C++运行时)的混合体。
相关文章:
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 复制包含C++所有元素的对象!(构造函数和赋值,最佳实践?
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++ 将函数指针与最佳性能相结合
- 在指向现有内存地址的 hpp 文件中声明成员函数的最佳方法
- std::使用类成员函数创建线程 - 最佳实践
- 将(临时的?)std::string传递给使用它来构造一个接受副本的对象的函数的最佳方法是什么?
- 在 c++ 或 python 中生成一个体面的视差图以在 Raspberry Pi 上实现的最佳方法(算法或函数)是什么
- 将uint8_t*buffer和size_tbufferlen从C++传递到C中的API函数的最佳方式是什么
- 从类中的对象调用类中的函数的最佳方法
- 这是使用构造函数初始化数组对象的最佳方法吗?
- 最佳做法:在函数中频繁使用大时态缓冲区 (C++)
- 在 c++ 中抽象两个略有不同的函数的最佳方法是什么?
- C++最佳实践:接受uint8_t、uint16_t、uint32_t、浮点数的函数
- 使用 emplace_back 避免移动构造函数调用的最佳方法?
- 调用不属于基类的派生类函数的最佳方法是什么?
- C++最佳实践 - 函数类型别名 std::function<T> 或 T
- C++ std::string 中是否有任何函数可以计算两个字符串的相同起始字符的总数或任何最佳方法
- 从C 中的函数中动态分配的缓冲区返回的最佳模式是什么?
- 字符传递给其他函数最佳实践