batuman
batuman

Reputation: 7304

Debug assertion failed using PInvoke to interface C/C++ DLL

I have a C/C++ dll and trying to interface to C# application using PInvoke. I got Debug assertion failed error. The dll works when interfaced to C++ application, the problem is only at interfaced to C# application. My DLL's .h and .cpp files are

Header file

#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 file

#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;
}

The error info is as shown in the attached picture.enter image description here

I used PInvoke as follow

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: I show an example of using PInvoke. What could be the difference from mine?

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);
   }
}

Upvotes: 0

Views: 493

Answers (1)

Ben Voigt
Ben Voigt

Reputation: 283733

You didn't show your p/invoke declarations, but there's a 100% chance you got it wrong, because there is no correct one. Those functions can't be directly called from C#, since their signatures are C++-specific.

The debug assertion trips because the C++ function tries to use its parameter as a std::string when it in fact is not one. The std::string destructor runs at the end of the scope, trying to free the memory... and fails because the memory wasn't allocated by the std::string constructor, because there is no std::string object in existence here.

You might add a wrapper that accepts some p/invoke-compatible string type such as a const char* or BSTR, creates a std::string, then calls the real functions.

In fact, you will also have trouble calling it from other C++ compilers or versions.

Upvotes: 2

Related Questions