Win32 c++ DLL函数在参数中获取垃圾值
Win32 C++ DLL function gets garbage values in parameters
我有一个Win32 c++ dll (a)调用另一个Win32 c++ dll (B). (B)使用LoadLibrary加载并包含一个方法:
Draw(HDC hDC, LPRECT lpRect, LPBUFFER buffer, LPOPTIONS options)
缓冲结构定义为:
struct Buffer
{
char* pData;
long Length;
TCHAR FileName[MAX_PATH];
Extension Extension;
};
typedef Buffer BUFFER, *LPBUFFER;
(A)用文件名、长度等填充BUFFER,并调用Draw函数。然后,Draw函数使用来自BUFFER的值。当dll被编译为64位时,它都可以正常工作,但如果我将它们编译为32位,那么我开始在缓冲区字段(B)中获取垃圾值。日志显示这些值在(A)中是好的,但当它们到达(B)时变成垃圾。
我尝试改变结构对齐选项/ZpX和调用约定绘制方法(__cdecl, __stdcall),但没有帮助。我认为这与调用约定有关,因为如果我改变绘制函数语法并将BUFFER作为第一个参数,那么(B)获得正确的值。这是怎么回事?
函数指针类型:
typedef bool (__cdecl *DrawFunc)(HDC hDC, LPRECT lpRect, LPBUFFER buffer, LPOPTIONS options);
然后在InitInstance中:
pDrawFunc = (DrawFunc)GetProcAddress(dllHandle, "Draw");
1. 如上所述,如果我把BUFFER作为第一个参数,那么它会收到正确的值。
2. HDC是一个单一的数值,总是接收正确的值
3.RECT得到不正确的值,非常大的值
我认为这个问题与结构体有关。只有结构才会得到错误的值。
更新2
好吧,我发现了我自己的愚蠢错误,Draw方法的声明是LPRECT,而实现是RECT,我的错,抱歉。但我仍然不确定为什么:
1. 其他参数显示垃圾值?
2. 为什么它能在64位运行?
Ok,我创建了一个具有3个项目的解决方案:库B,包含Draw(),库a,具有Test(),加载库B并调用Draw()与一些缓冲区*和应用程序测试,与库a链接并调用Test()。32位和64位都可以正常工作。Test()的一小段代码:
#include "stdafx.h"
#include "A.h"
#include "../B/B.h"
namespace {
LPBUFFER CreateBuffer(const char* const data, LPCTSTR const name)
{
if(!data || !name)
return NULL;
LPBUFFER buffer = new BUFFER();
buffer->Length = static_cast<long>(strlen(data) + 1);
buffer->pData = new char[buffer->Length];
strcpy_s(buffer->pData, buffer->Length * sizeof(char), data);
buffer->Extension = 0;
::ZeroMemory(buffer->FileName, _countof(buffer->FileName) * sizeof(TCHAR));
_tcscpy_s(buffer->FileName, name);
return buffer;
}
void DestroyBuffer(LPBUFFER buffer)
{
delete [] buffer->pData;
buffer->Length = 0;
buffer->pData = NULL;
buffer->Extension = 0;
::ZeroMemory(buffer->FileName, _countof(buffer->FileName) * sizeof(TCHAR));
delete buffer;
}
} // namespace
A_API void Test()
{
HMODULE b_lib = ::LoadLibrary(_T("B.dll"));
if(!b_lib)
{
::OutputDebugString(_T("Can't load libraryn"));
return;
}
typedef bool (*DrawFunction)(HDC hDC, LPRECT lpRect, LPBUFFER buffer, LPOPTIONS options);
DrawFunction draw = reinterpret_cast<DrawFunction>(::GetProcAddress(b_lib, "Draw"));
if(!draw)
{
::OutputDebugString(_T("Can't get address of Draw()"));
goto FINISH_LABEL;
}
LPBUFFER buffer = CreateBuffer("test", _T("path"));
draw(NULL, NULL, buffer, NULL);
DestroyBuffer(buffer);
FINISH_LABEL:
::FreeLibrary(b_lib);
b_lib = NULL;
}
和一个完整的解决方案:https://www.dropbox.com/s/5ei6ros9e8s94e2/B.zip
- 有没有办法在从编译器获取参数时避免预处理器宏?
- 如何使用可变参数模板获取参数的变量号及其大小C++
- 如何从 x64 程序集中的堆栈中获取参数?
- 从命令行获取参数时出现问题
- 函数获取参数的变量列表并将它们转换为一系列字节?
- 当函数在C++中获取参数时,为什么要使用取消引用
- C++是否在 for 循环之前获取参数
- 为什么相同的函数签名只有区别,另一个通过 const 获取参数是重新定义?
- 获取参数的子类
- 如何循环访问在 cmd 中获取参数的 exe 文件
- 一种从元组/数组获取参数包的方法
- 如何获取参数包中元素的索引
- 延长函数的寿命延长 由 const& 获取参数并由 const& 返回
- 我的二传手可以获取参数,但实际上不能?
- 如何获取参数[0]
- 可以用于获取参数类型的 decltype
- 使用常量,获取参数表而不是复制
- C++11、14 或 17 是否提供了一种从 decltype() 中获取参数的方法?
- 根据给定的索引集获取参数包的子集
- 为什么 std::not1() 通过常量引用而不是按值获取参数