Win32 c++ DLL函数在参数中获取垃圾值

Win32 C++ DLL function gets garbage values in parameters

本文关键字:获取 参数 c++ DLL 函数 Win32      更新时间:2023-10-16

我有一个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