Shared memory between C++ DLL and C# code
<p>I am currently working on a project with really short deadline, so I don't have much time to understand everything. Also, I am <strong>not</strong> an expert in C++ development and memory management.</p>

<p>So, what I am trying to do is to create a DLL in with both C and C++ code. Then, I would like to call this DLL in a C# code. Currently, the communication between C++ and C# is OK. The problem comes up when I try to transfer a string from the DLL to the C# code. The error is this one : </p>

<pre><code>System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at Microsoft.Win32.Win32Native.CoTaskMemFree(IntPtr ptr)
   at System.StubHelpers.CSTRMarshaler.ClearNative(IntPtr pNative)
   at NMSPRecognitionWrapper.Program.GetResultsExt()
   at NMSPRecognitionWrapper.Program.&lt;Main&gt;b__0() in &lt;my dir&gt;\Program.cs:line 54
   at NMSPRecognitionWrapper.Program.StartRecognitionExt()
   at NMSPRecognitionWrapper.Program.Main(String[] args) in &lt;my dir&gt;\Program.cs:line 60
</code></pre>

<p>Also, I can give you some piece of code below (really simplified !). Actually, the C++ expose two methods : <code>StartRecognition()</code> launch operations to get some data from microphone, then process them and store the results. <code>GetResults()</code> return an instance of the results previously stored. The <code>WrapperCallback()</code> allows the C# part to be called when a Result is able for processing. The C# part, when the Callback is called, will ask to get the results using the <code>GetResults()</code> method.</p>

<p>I know the architecture may seem really inappropriate in this presentation, but I don't want to explain the whole project to validate the model, please be sure everything is correct.</p>

<p>To finish, the problem is when the C# callback call the <code>GetResults()</code> method. Trying to access to the <code>resultsForCS</code> seems to be impossible from the C#.</p>

<p><strong>C++ part - header</strong>
</p>

<pre><code>// NMSPRecognitionLib.h

#pragma once
#include &lt;iostream&gt;

using namespace std;

extern "C" __declspec(dllexport) char* GetResults();
extern "C" static void DoWork();
extern "C" __declspec(dllexport) void StartRecognition();
</code></pre>

<p><strong>C++ part - sources</strong>
</p>

<pre><code>#include "stdafx.h"
#include "NMSPRecognitionLib.h"

static char * resultsForCS;

static SUCCESS ProcessResult(NMSPCONNECTION_OBJECTS *pNmspConnectionObjects, LH_OBJECT hResult)
{
    [...]
    char* szResult;
    [...]

    resultsForCS = szResult;

    DoWork();

    [...]
    return Success;

    error:
        return Failure;
} /* End of ProcessResult */


extern "C" __declspec(dllexport) char* GetResults()
{
    return resultsForCS;
}

extern "C"
{
    typedef void (*callback_function)();
    callback_function gCBF;

    __declspec(dllexport) void WrapperCallback(callback_function callback) {
        gCBF = callback;
    }

    static void DoWork() {
        gCBF();
    }
}

extern "C" __declspec(dllexport) void StartRecognition()
{
    char* argv[] = { "path", "params" };
    entryPoint(2, argv);
}
</code></pre>

<p><strong>C# part</strong>
</p>

<pre><code>class Program
{
    [DllImport("NMSPRecognitionLib.dll", EntryPoint = "GetResults")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string GetResultsExt();

    public delegate void message_callback_delegate();

    [DllImport("NMSPRecognitionLib.dll", EntryPoint = "WrapperCallback")]
    public static extern void WrapperCallbackExt(message_callback_delegate callback);

    [DllImport("NMSPRecognitionLib.dll", EntryPoint = "StartRecognition")]
    public static extern void StartRecognitionExt();

    static void Main(string[] args)
    {
        WrapperCallbackExt(
            delegate()
            {
                Console.WriteLine(GetResultsExt());
            }
        );

        StartRecognitionExt();

        Console.WriteLine("\nPress any key to finish... ");
        var nothing = Console.ReadLine();
    }
}
</code></pre>

<p>I understand that the problem comes because I am using a pointer to store the results (<code>char *</code>), but I actually don't know how to do this in another way. The <code>szResults</code> type is <code>char *</code> too and I can't change this !</p>
