System.AccessViolationException:试图在 C++ dll 中读取或写入受保护的内存
System.AccessViolationException : Attempted to read or write protected memory in C++ dll
所以我已经为此绞尽脑汁了一段时间。我构建了一个用于 VB.net 项目的 C++ dll。 C++源码如下所示
C++
#include "stdafx.h"
#include "mydll.h"
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <fstream>
extern "C" __declspec(dllexport) void __cdecl ExtractVolumeDataC(std::string path, std::string fileName, bool chkVol, std::string txtKeyName)
{
std::string line;
std::vector<std::vector<std::string>> ValuesCSV;
std::replace(path.begin(), path.end(), '\', '/'); //replace backslash with forward slash
std::ifstream in(path + fileName);
while (std::getline(in, line)) {
std::string phrase;
std::vector<std::string> row;
std::stringstream ss(line);
while (std::getline(ss, phrase, ',')) {
row.push_back(std::move(phrase));
}
ValuesCSV.push_back(std::move(row));
}
}
我在VB.net中使用的代码如下
VB.net
Public Class Form1
<Runtime.InteropServices.DllImport("mydll.dll")> _
Public Shared Sub ExtractVolumeDataC(ByVal path As String, ByVal fileName As String, ByVal txtKeyName As String)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ExtractVolumeDataC("C:\users\me\documents\", "VOL.CSV", "01100872")
End Sub
End Class
我观察到的一个问题是,我在使用基元时没有遇到此错误,但包括 string
和 vector
等 STL 元素。我得到了错误。如果这是一个愚蠢的问题,我很抱歉我已经 15 年没有看过 C++ 代码了。
VB.net 不将字符串作为 c++ std::string
传递,ByVal
字符串作为指向字符的指针传递(即旧的 C 样式字符串)。您可以使用 LPCSTR
作为参数类型。在您的情况下,这将是:
extern "C" __declspec(dllexport) void __cdecl ExtractVolumeDataC(LPCSTR path, LPCSTR fileName, bool chkVol, LPCSTR txtKeyName)
有关详细信息,请参阅 This Microsoft support page。
不得在 dll 中使用 STL 元素。它们没有明确地从 dll 中导出。最好的方法是始终对 DLL 中的导出函数使用 C 样式代码。
这里是某人关于 dll 中使用的 STL 的回答。
returning std::string/std::list from dll
所以我已经为此绞尽脑汁了一段时间。我构建了一个用于 VB.net 项目的 C++ dll。 C++源码如下所示
C++
#include "stdafx.h"
#include "mydll.h"
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <fstream>
extern "C" __declspec(dllexport) void __cdecl ExtractVolumeDataC(std::string path, std::string fileName, bool chkVol, std::string txtKeyName)
{
std::string line;
std::vector<std::vector<std::string>> ValuesCSV;
std::replace(path.begin(), path.end(), '\', '/'); //replace backslash with forward slash
std::ifstream in(path + fileName);
while (std::getline(in, line)) {
std::string phrase;
std::vector<std::string> row;
std::stringstream ss(line);
while (std::getline(ss, phrase, ',')) {
row.push_back(std::move(phrase));
}
ValuesCSV.push_back(std::move(row));
}
}
我在VB.net中使用的代码如下
VB.net
Public Class Form1
<Runtime.InteropServices.DllImport("mydll.dll")> _
Public Shared Sub ExtractVolumeDataC(ByVal path As String, ByVal fileName As String, ByVal txtKeyName As String)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ExtractVolumeDataC("C:\users\me\documents\", "VOL.CSV", "01100872")
End Sub
End Class
我观察到的一个问题是,我在使用基元时没有遇到此错误,但包括 string
和 vector
等 STL 元素。我得到了错误。如果这是一个愚蠢的问题,我很抱歉我已经 15 年没有看过 C++ 代码了。
VB.net 不将字符串作为 c++ std::string
传递,ByVal
字符串作为指向字符的指针传递(即旧的 C 样式字符串)。您可以使用 LPCSTR
作为参数类型。在您的情况下,这将是:
extern "C" __declspec(dllexport) void __cdecl ExtractVolumeDataC(LPCSTR path, LPCSTR fileName, bool chkVol, LPCSTR txtKeyName)
有关详细信息,请参阅 This Microsoft support page。
不得在 dll 中使用 STL 元素。它们没有明确地从 dll 中导出。最好的方法是始终对 DLL 中的导出函数使用 C 样式代码。
这里是某人关于 dll 中使用的 STL 的回答。
returning std::string/std::list from dll