使用 PInvoke 连接 C/C++ DLL 的调试断言失败
Debug assertion failed using PInvoke to interface C/C++ DLL
我有一个 C/C++ dll 并尝试使用 PInvoke 连接到 C# 应用程序。
我收到 Debug assertion failed
错误。该 dll 在与 C++ 应用程序接口时工作,问题仅在与 C# 应用程序接口时出现。
我的 DLL 的 .h 和 .cpp 文件是
头文件
#include <string>
#include <fstream>
#include <iostream>
#ifdef DLL_EXPORTS
#define DLL_EXPORTS __declspec(dllexport)
#else
#define DLL_EXPORTS __declspec(dllimport)
#endif
#define PASS 0
#define FILECREATE_FAIL 1
#define CAMERA_ERROR 2
#define MAX_NUM_FRAMES 10000
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
// Returns pass 0
// Fails 1
// Open the file at the path and start acquisition
DLL_EXPORTS int start_acquisition(string path);
DLL_EXPORTS int stop_acquisition();
#ifdef __cplusplus
}
#endif
CPP 文件
#include "stdafx.h"
#include "IntensityDll.h"
#include <sstream>
ofstream fileout;
int counter;
char Header[64];
short Image[MAX_NUM_FRAMES][6400];
int ret;
int acquisition();
int start_acquisition(std::string path)
{
ret = PASS;
try
{
fileout.open(path);//fstream
if (fileout.is_open()) {
ret = acquisition();
}
}
catch(fstream::failure e)
{
cout << "Exception opening/reading file. " << endl;;
return FILECREATE_FAIL;
}
return ret;
}
错误信息如附图所示
我使用 PInvoke 如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("C:\WindowsFormsApplication1\WindowsFormsApplication1\Wavelength_MaxIntensityDll.dll")]
public static extern int start_acquisition(string path);
[DllImport("C:\WindowsFormsApplication1\Wavelength_MaxIntensityDll.dll")]
public static extern int stop_acquisition();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int ret = start_acquisition("C:\Users\nyan2012\Desktop\Wavelength_test\test1.txt");
}
}
}
编辑 1:
我展示了一个使用 PInvoke 的例子。和我的有什么不同?
class PlatformInvokeTest
{
[DllImport("user32.dll")]
public static extern int MessageBoxA(
int h, string m, string c, int type);
public static int Main()
{
return MessageBoxA(0, "Hello World!", "My Message Box", 0);
}
}
您没有显示您的 p/invoke 声明,但您有 100% 的可能弄错了,因为没有正确的声明。这些函数不能直接从 C# 调用,因为它们的签名是特定于 C++ 的。
调试断言失败,因为 C++ 函数试图将其参数用作 std::string
,而实际上它不是一个。 std::string
析构函数在范围的末尾运行,试图释放内存...但失败了,因为 std::string
构造函数没有分配内存,因为 没有std::string
此处存在对象。
您可以添加一个包装器,它接受一些 p/invoke 兼容的字符串类型,例如 const char*
或 BSTR
,创建一个 std::string
,然后调用真正的函数.
事实上,从其他 C++ 编译器或版本调用它也会遇到问题。
我有一个 C/C++ dll 并尝试使用 PInvoke 连接到 C# 应用程序。
我收到 Debug assertion failed
错误。该 dll 在与 C++ 应用程序接口时工作,问题仅在与 C# 应用程序接口时出现。
我的 DLL 的 .h 和 .cpp 文件是
头文件
#include <string>
#include <fstream>
#include <iostream>
#ifdef DLL_EXPORTS
#define DLL_EXPORTS __declspec(dllexport)
#else
#define DLL_EXPORTS __declspec(dllimport)
#endif
#define PASS 0
#define FILECREATE_FAIL 1
#define CAMERA_ERROR 2
#define MAX_NUM_FRAMES 10000
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
// Returns pass 0
// Fails 1
// Open the file at the path and start acquisition
DLL_EXPORTS int start_acquisition(string path);
DLL_EXPORTS int stop_acquisition();
#ifdef __cplusplus
}
#endif
CPP 文件
#include "stdafx.h"
#include "IntensityDll.h"
#include <sstream>
ofstream fileout;
int counter;
char Header[64];
short Image[MAX_NUM_FRAMES][6400];
int ret;
int acquisition();
int start_acquisition(std::string path)
{
ret = PASS;
try
{
fileout.open(path);//fstream
if (fileout.is_open()) {
ret = acquisition();
}
}
catch(fstream::failure e)
{
cout << "Exception opening/reading file. " << endl;;
return FILECREATE_FAIL;
}
return ret;
}
错误信息如附图所示
我使用 PInvoke 如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("C:\WindowsFormsApplication1\WindowsFormsApplication1\Wavelength_MaxIntensityDll.dll")]
public static extern int start_acquisition(string path);
[DllImport("C:\WindowsFormsApplication1\Wavelength_MaxIntensityDll.dll")]
public static extern int stop_acquisition();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int ret = start_acquisition("C:\Users\nyan2012\Desktop\Wavelength_test\test1.txt");
}
}
}
编辑 1: 我展示了一个使用 PInvoke 的例子。和我的有什么不同?
class PlatformInvokeTest
{
[DllImport("user32.dll")]
public static extern int MessageBoxA(
int h, string m, string c, int type);
public static int Main()
{
return MessageBoxA(0, "Hello World!", "My Message Box", 0);
}
}
您没有显示您的 p/invoke 声明,但您有 100% 的可能弄错了,因为没有正确的声明。这些函数不能直接从 C# 调用,因为它们的签名是特定于 C++ 的。
调试断言失败,因为 C++ 函数试图将其参数用作 std::string
,而实际上它不是一个。 std::string
析构函数在范围的末尾运行,试图释放内存...但失败了,因为 std::string
构造函数没有分配内存,因为 没有std::string
此处存在对象。
您可以添加一个包装器,它接受一些 p/invoke 兼容的字符串类型,例如 const char*
或 BSTR
,创建一个 std::string
,然后调用真正的函数.
事实上,从其他 C++ 编译器或版本调用它也会遇到问题。