У меня есть C/C++ dll и пытаюсь взаимодействовать с С# -приложением, используя PInvoke. Я получил сообщение об ошибке "Ошибка Debug assertion failed
. DLL работает при взаимодействии с приложением 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");
}
}
}
EDIT 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++ пытается использовать свой параметр как std::string
когда это фактически не одно. std::string
destructor работает в конце области действия, пытаясь освободить память... и терпит неудачу, потому что память не была выделена конструктором std::string
, потому что нет объекта std::string
здесь.
Вы можете добавить оболочку, которая принимает некоторый тип строки, совместимый с p/invoke, такой как const char*
или BSTR
, создает std::string
, а затем вызывает реальные функции.
На самом деле вам также будет сложно вызвать его из других C++ компиляторов или версий.
__cplusplus
в заголовочном файле абсолютно бесполезен, так как эти функции используют типы, которых нет в C.