VS2013 构建的 C++/CLI DLL 使用从 VS2008 C++ 应用程序接收的字符串崩溃
VS2013-built C++/CLI DLL crashes using string received from VS2008 C++ app
我使用 VS2013 创建了一个 Visual C++ CLR class 库,没有对项目设置进行任何更改。目标框架 = .NET 4.5.2.
引用 System.Windows.Forms 并将字符串添加到 stdafx.h。
ClassLibrary1.h:
#pragma once
#if defined DO_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
using namespace System;
extern "C"
{
DECLDIR void Foo();
DECLDIR void Foo2a();
DECLDIR void Foo2b(std::string s);
}
ClassLibary1.cpp:
#define DO_EXPORT
#include "stdafx.h"
#include "ClassLibrary1.h"
using namespace System::Windows::Forms;
void FooImp()
{
}
void FooImp2(std::string s)
{
}
extern "C"
{
void Foo()
{
::FooImp();
}
void Foo2a()
{
MessageBox::Show("Entered Foo2a");
::FooImp2("");
MessageBox::Show("Exited Foo2a");
}
void Foo2b(std::string s)
{
MessageBox::Show("Entered Foo2b");
::FooImp2(s);
MessageBox::Show("Exited Foo2b");
}
}
以上代码在构建到 VS2013 C++ Win32 控制台应用程序时工作正常(将字符串和 windows.h 添加到 stdafx.h,并且不更改项目设置):
typedef void(*VoidFuncVoid)(void);
typedef void(*VoidFuncStr)(std::string);
int _tmain(int argc, _TCHAR* argv[])
{
VoidFuncVoid _Foo;
VoidFuncVoid _Foo2a;
VoidFuncStr _Foo2b;
HINSTANCE hInstLibrary1 = LoadLibrary(_T("ClassLibrary1.dll"));
if (hInstLibrary1)
{
_Foo = reinterpret_cast<VoidFuncVoid>(GetProcAddress(hInstLibrary1, "Foo"));
_Foo();
_Foo2a = reinterpret_cast<VoidFuncVoid>(GetProcAddress(hInstLibrary1, "Foo2a"));
_Foo2a();
_Foo2b = reinterpret_cast<VoidFuncStr>(GetProcAddress(hInstLibrary1, "Foo2b"));
_Foo2b("");
FreeLibrary(hInstLibrary1);
}
}
所有 Foo 调用都很好,我收到了四个消息提示。
但是,当将相同的代码构建到 VS2008 C++ Win32 控制台应用程序时(将字符串和 windows.h 添加到 stdafx.h,并且不更改项目设置),应用程序在两个 Foo2b 消息提示,报告:
Unhandled exception at 0x0f5433be in ConsoleApp1.exe: 0xC0000005:
Access violation reading location 0x002d1000.
我错过了什么? ::FooImp2(s); 出了什么问题?声明?
要使用 Visual Studio 内置的库,该库已导出带有标准库参数的 C++ 函数或 类 具有标准库成员,您基本上必须使用相同版本的 Visual Studio为客户。这是因为 Visual Studio 的每个新版本都会对标准库进行更改(因此客户对 std::string
或 std::vector
的看法与编译到库中的内容不同)。
如果您需要使用不同版本的 Visual Studio 构建客户端和库,唯一安全的方法是使用严格的 C 接口公开您需要的代码(const char *
而不是 std::string
,int ar[], int arCount
而不是 std::vector<int>
)。
我使用 VS2013 创建了一个 Visual C++ CLR class 库,没有对项目设置进行任何更改。目标框架 = .NET 4.5.2.
引用 System.Windows.Forms 并将字符串添加到 stdafx.h。
ClassLibrary1.h:
#pragma once
#if defined DO_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
using namespace System;
extern "C"
{
DECLDIR void Foo();
DECLDIR void Foo2a();
DECLDIR void Foo2b(std::string s);
}
ClassLibary1.cpp:
#define DO_EXPORT
#include "stdafx.h"
#include "ClassLibrary1.h"
using namespace System::Windows::Forms;
void FooImp()
{
}
void FooImp2(std::string s)
{
}
extern "C"
{
void Foo()
{
::FooImp();
}
void Foo2a()
{
MessageBox::Show("Entered Foo2a");
::FooImp2("");
MessageBox::Show("Exited Foo2a");
}
void Foo2b(std::string s)
{
MessageBox::Show("Entered Foo2b");
::FooImp2(s);
MessageBox::Show("Exited Foo2b");
}
}
以上代码在构建到 VS2013 C++ Win32 控制台应用程序时工作正常(将字符串和 windows.h 添加到 stdafx.h,并且不更改项目设置):
typedef void(*VoidFuncVoid)(void);
typedef void(*VoidFuncStr)(std::string);
int _tmain(int argc, _TCHAR* argv[])
{
VoidFuncVoid _Foo;
VoidFuncVoid _Foo2a;
VoidFuncStr _Foo2b;
HINSTANCE hInstLibrary1 = LoadLibrary(_T("ClassLibrary1.dll"));
if (hInstLibrary1)
{
_Foo = reinterpret_cast<VoidFuncVoid>(GetProcAddress(hInstLibrary1, "Foo"));
_Foo();
_Foo2a = reinterpret_cast<VoidFuncVoid>(GetProcAddress(hInstLibrary1, "Foo2a"));
_Foo2a();
_Foo2b = reinterpret_cast<VoidFuncStr>(GetProcAddress(hInstLibrary1, "Foo2b"));
_Foo2b("");
FreeLibrary(hInstLibrary1);
}
}
所有 Foo 调用都很好,我收到了四个消息提示。
但是,当将相同的代码构建到 VS2008 C++ Win32 控制台应用程序时(将字符串和 windows.h 添加到 stdafx.h,并且不更改项目设置),应用程序在两个 Foo2b 消息提示,报告:
Unhandled exception at 0x0f5433be in ConsoleApp1.exe: 0xC0000005: Access violation reading location 0x002d1000.
我错过了什么? ::FooImp2(s); 出了什么问题?声明?
要使用 Visual Studio 内置的库,该库已导出带有标准库参数的 C++ 函数或 类 具有标准库成员,您基本上必须使用相同版本的 Visual Studio为客户。这是因为 Visual Studio 的每个新版本都会对标准库进行更改(因此客户对 std::string
或 std::vector
的看法与编译到库中的内容不同)。
如果您需要使用不同版本的 Visual Studio 构建客户端和库,唯一安全的方法是使用严格的 C 接口公开您需要的代码(const char *
而不是 std::string
,int ar[], int arCount
而不是 std::vector<int>
)。