0

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);
   }
}
2
  • 1
    The __cplusplus test in the header file is totally useless, since those functions use types that don't exist in C. Commented Jan 12, 2015 at 4:42
  • The unmanaged function in your question using cdecl calling convention. The default for p/invoke is stdcall. Commented Jan 12, 2015 at 9:07

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

I have updated in EDIT 1. I feel like I understand what you tried to explain. But according to the example I updated, what is the difference from mine?
The difference is that the MessageBoxA function uses const char* not C++ std::string. There is nothing in C# that can call a function that uses a std::string parameter.
It is a little bit weird now. Now I don't have any argument to dll call and the path "C:\\Users\\nyan2012\\Desktop\\Wavelength_test\\test1.txt" is assigned in C++ dll code. So C# code just call dll but no parameter passing. For the dll, if called from C# application it has the error of "Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt." But no error when called from C++ application. What is the idea behind?
Now you are asking why your code, which we cannot see, is wrong. Why don't you stick to the question that you asked? Ben has given you the correct answer. You are now able to accept his answer, and then worry about your new problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.