DLL 导致"Microsoft Excel has stopped working"但它在 Win32 控制台应用中工作正常
DLL causes "Microsoft Excel has stopped working" but it works fine in Win32 console app
这将是
一篇很长的文章,但我不确定需要哪些信息来正确解释这个问题。 我有一个C++ DLL,我正在尝试从 Excel 调用它。 每当我调用它时,其中一个函数都会导致 Excel 崩溃并显示"Microsoft Excel 已停止工作"。
头文件:
#include <string>
namespace XYZ_ProjectWise
{
class FileOperator
{
public:
static __declspec(dllexport) long __stdcall initialize(std::string dbName);
static __declspec(dllexport) long __stdcall openDoc(long projectID,long docID);
};
}
initialize()
的功能代码:
long FileOperator::initialize(string dbName)
{
LPCWSTR user=L"";
LPCWSTR pwd=L"";
LPCWSTR schema=L"";
std::wstring sTemp=std::wstring(dbName.begin(),dbName.end());
LPCWSTR dbName_L=sTemp.c_str();
bool resultInit=aaApi_Initialize(AAMODULE_ALL);
bool resultLogin=aaApi_Login(AAAPIDB_UNKNOWN,dbName_L,user,pwd,schema);
return 0;
}
垃圾桶产量/出口量:
?initialize@FileOperator@XYZ_ProjectWise@@SGJV?$basic_string@DU?$char_traits@D@std@@V?
$allocator@D@2@@std@@@Z
VBA 中的声明:
Private Declare Function initialize Lib "C:Program Files
(x86)BentleyProjectWisebinXYZ_ProjectWiseDLL.dll" _
Alias "?initialize@FileOperator@XYZ_ProjectWise@@SGJV?$basic_string@DU?
$char_traits@D@std@@V?$allocator@D@2@@std@@@Z" _
(ByVal dbName As String) As Long
它在 VBA 中的调用方式:
Public Sub testDLL()
Dim result As Long
result = initialize("ABC.DEF.GHI.com:PWOPPID_XYZ")
End Sub
奇怪的是,如果我在openDoc()
函数中包含initialize()
函数代码,dbName
硬编码,并按如下方式自行调用openDoc()
,则不会发生崩溃:
long __stdcall FileOperator::openDoc(long projectID,long docID)
{
LPCWSTR dbName=L"ABC.DEF.GHI.com:PWOPPID_XYZ";
LPCWSTR user=L"";
LPCWSTR pwd=L"";
LPCWSTR schema=L"";
bool resultInit=aaApi_Initialize(AAMODULE_ALL);
bool resultLogin=aaApi_Login(AAAPIDB_UNKNOWN,dbName,user,pwd,schema);
long resultOpen=aaApi_OpenDocument(projectID,docID,false);
return resultOpen;
}
}
VBA 调用:
Private Declare Function openDoc Lib "C:Program Files
(x86)BentleyProjectWisebinXYZ_ProjectWiseDLL.dll" _
Alias "?openDoc@FileOperator@XYZ_ProjectWise@@SGJJJ@Z" _
(ByVal projectID As Long, ByVal docID As Long) As Long
Public Sub testDLL()
Dim result As Long
result = openDoc(1799,29)
End Sub
那么,为什么 VBA 调用initialize()
崩溃,但 VBA 调用中的相同代码openDoc()
工作正常?
明显的问题是C++代码使用了对互操作无效的C++类。VBA 编组器根本无法提供 std::string。仅使用简单的 POD 类型进行互操作。
在C++端,对于字符串参数,接收指向以空结尾的字符数组 const char* 的指针。由于 std::string 有一个接受 const char* 的构造函数,因此很容易使这样的参数适应您的需求。
在 VBA 端,您将字符串参数声明为按值字符串,VBA 封送器将转换为 char*。您已经这样做了,因此您唯一需要的更改是在C++代码中。
相关文章:
- C++控制台应用程序阻止退出
- 如何从 Win32 C++ 应用程序输出到父控制台窗口?
- 如何在 Win32 C++控制台应用程序中调用 UWP 类库
- 什么是仅调用一次并调用参数的控制台应用
- 是否可以从控制台应用程序使用 C++/WinRT 创建窗口?
- 如何创建一个使用开源c项目的c++控制台应用程序
- c ++控制台应用程序,如何在控制台外部打印字符
- 像 CPP 中的控制台一样的应用程序
- 调试控制台 ChessEngine.exe "used"在另一个应用程序(国际象棋 GUI)中
- 为什么我不能在同一 MS VS 解决方案中的两个控制台应用中使用C++特征(仅标头库)?
- 将控制台应用程序直接输出到Visual Studio而不是外部Windows控制台中
- 如何在 Win32 控制台应用程序中注册不可见的窗口类?
- C++控制台应用,其中有两个冲突的对象不工作
- 如何将从控制台应用程序C++回调设置为C++ COM DLL
- 使用代码在 AWS 开发工具包C++控制台应用程序上设置凭证
- 直接输入控制台应用程序
- C++调试控制台应用程序
- C++控制台应用程序调用C++/CLI静态库
- 如何在控制台应用程序中添加滚动功能以显示更大的输入
- 如何在将Visual Studio C++控制台应用程序连接到Microsoft SQL Server时修复"