gpt4 book ai didi

c++ - 当 VBA 运行声明的函数但 C++ 控制台应用程序运行正常时堆损坏?

转载 作者:太空宇宙 更新时间:2023-11-04 13:58:24 27 4
gpt4 key购买 nike

我正在使用 Visual C++ 2012 创建一个包装函数,用于从 VBA 调用 API。如果重要的话,这是针对 Bentley ProjectWise API 的,我正在调用 aaApi_DocumentSelectDlg()

当我从 C++ 控制台应用程序运行此函数时,该函数有效,但当我从 VBA 调用它并单步执行该函数时,API 调用会导致堆损坏错误。

这是包装函数:

//function for opening a file select dialog and getting the IDs associated with
//that file
long __stdcall FileOperator::selectFile(long* docArray)
{
try
{
//set parameters for dialog
AAOPENDOCSDLG2_PARAM param={0};
param.ulMask |= AAOPENDLG2_MASK_FLAGS|AAOPENDLG2_MASK_TITLE|AAOPENDLG2_MASK_PROJECTID|
AAOPENDLG2_MASK_DOCUMENTID|AAOPENDLG2_MASK_FILENAME;
param.ulFlags = AAOPENDLG2_SINGLE_SELECTION | AAOPENDLG2_GET_IDS_ONLY | AAOPENDLG2_HIDEREADONLY | AAOPENDLG2_NO_USE_LASTPROJ;
param.lpctstrTitle = L"Select a file";

//open dialog, get result of user's selection
long result=aaApi_DocumentSelectDlg(&param);

//set array values to pass file info out of function
if(result==IDOK)
{
docArray[0]=param.plProjectIds[0];
docArray[1]=param.plDocumentIds[0];
}
else
{
docArray[0]=0;
docArray[1]=0;
}
return 1;
}
catch (exception& e)
{
//error string not returned, just used for debugging
string error=e.what();
return 0;
}
}

这是成功执行的控制台应用程序:

int main()
{
//initialization function for opening session with database. no problem here.
long initResult=TestDLL::FileOperator::initialize("Test.QA.com:PWOPPID_XYZ");

long selectResultArray[2]={0};
TestDLL::FileOperator::selectFile(selectResultArray);

return 0;
}

下面是导致堆损坏的 VBA 代码:

Private Declare Function selectFile _
Lib "C:\Program Files (x86)\Bentley\ProjectWise\bin\TestDLL.dll" _
Alias "?selectFile@FileOperator@TestDLL@@SGJPAJ@Z" _
(ByRef docArray As Long) As Long

Public Function selectPWFolder() As Long

Dim docArray(1) As Long
Dim result As Long

docArray(0) = 0
docArray(1) = 0
result = selectFile(docArray(LBound(docArray)))
selectPWFolder = docArray(1)

End Function

我已经通过设置调试器将其缩小到 API 调用,以便在 VBA 调用 selectFile() 时它进入 C++ 代码。我通过将 EXCEL.EXE 设置为 Debugging->Command,并将 C/C++->Browse Information->Enable Browse Information 设置为“Yes (/FR)”来做到这一点。

令人费解的是,当从 VBA 调用时,函数中唯一不同(或看起来)的元素是 docArray 参数,它甚至没有被 selectFile( ) 直到 API 调用之后。当我到达 aaApi_DocumentSelectDlg() 行并进入它时,我收到以下错误消息:

Critical error detected c0000374
EXCEL.EXE has triggered a breakpoint.
First-chance exception at 0x77E0E753 (ntdll.dll) in EXCEL.EXE: 0xC0000374:
A heap has been corrupted (parameters: 0x77E44270).

为什么 VBA 会导致这种堆损坏?我正在传递一个指向 docArray 的第一个元素的指针,这样我就可以将数组从 VBA 传递给 DLL 函数而不必使用 SAFEARRAY,但我认为这不是问题所在,因为调用 aaApi_DocumentSelectDlg() 不使用 docArray

编辑:我制作了另一个不接受任何参数的 selectFile() 版本,以测试在没有 docArray 的情况下是否发生错误。堆损坏错误仍然发生。所以它与API调用本身有关,与传递数组无关。

初始化函数的代码是:

long FileOperator::initialize(char* dbName)
{
LPCWSTR user=L"";
LPCWSTR pwd=L"";
LPCWSTR schema=L"";
std::string dbNameStr=std::string(dbName);
std::wstring sTemp=std::wstring(dbNameStr.begin(),dbNameStr.end());
LPCWSTR dbName_L=sTemp.c_str();
bool resultInit=aaApi_Initialize(AAMODULE_ALL);
bool resultLogin=aaApi_Login(AAAPIDB_UNKNOWN,dbName_L,user,pwd,schema);
if (resultInit&&resultLogin)
{
return 11;
}
else if (resultInit&&!resultLogin)
{
return 10;
}
else if ((!resultInit)&&resultLogin)
{
return 1;
}
else
{
return 0;
}
}

最佳答案

尝试将您的 VBA 更改为:

Private Declare Function selectFile _
Lib "C:\Program Files (x86)\Bentley\ProjectWise\bin\TestDLL.dll" _
Alias "?selectFile@FileOperator@TestDLL@@SGJPAJ@Z" _
(ByVal lpdocArray As Long) As Long

Public Function selectPWFolder() As Long

Dim docArray(1) As Long
Dim result As Long

docArray(0) = 0
docArray(1) = 0
result = selectFile(VarPtr(docArray(0)))
selectPWFolder = docArray(1)

End Function

这显式地向函数发送了数组第一个元素的地址。

关于c++ - 当 VBA 运行声明的函数但 C++ 控制台应用程序运行正常时堆损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20357972/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com