私は現在、締め切りが非常に短いプロジェクトに取り組んでいるので、すべてを理解する時間があまりありません。また、私はC++ 開発とメモリ管理の専門家ではありません。
だから、私がやろうとしているのは、C と C++ の両方のコードで DLL を作成することです。次に、この DLL を C# コードで呼び出したいと思います。現在、C++ と C# 間の通信は問題ありません。DLL から C# コードに文字列を転送しようとすると、問題が発生します。エラーはこれです:
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.<Main>b__0() in <my dir>\Program.cs:line 54
at NMSPRecognitionWrapper.Program.StartRecognitionExt()
at NMSPRecognitionWrapper.Program.Main(String[] args) in <my dir>\Program.cs:line 60
また、以下にいくつかのコードを示します (非常に単純化されています!)。実際、C++ は 2 つのメソッドを公開しています。StartRecognition()
操作を起動してマイクからデータを取得し、それらを処理して結果を保存します。GetResults()
以前に保存された結果のインスタンスを返します。これWrapperCallback()
により、Result が処理可能になったときに C# 部分を呼び出すことができます。Callback が呼び出されると、C# 部分はGetResults()
メソッドを使用して結果を取得するように要求します。
このプレゼンテーションではアーキテクチャが不適切に見えるかもしれませんが、モデルを検証するためにプロジェクト全体を説明するつもりはありません。すべてが正しいことを確認してください。
最後に、問題は C# コールバックがGetResults()
メソッドを呼び出すときです。C#からアクセスしようとしてresultsForCS
も無理のようです。
C++ 部分 - ヘッダー
// NMSPRecognitionLib.h
#pragma once
#include <iostream>
using namespace std;
extern "C" __declspec(dllexport) char* GetResults();
extern "C" static void DoWork();
extern "C" __declspec(dllexport) void StartRecognition();
C++ 部分 - ソース
#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);
}
C#部分
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();
}
}
結果を格納するためにポインターを使用しているために問題が発生することは理解していますが ( char *
)、実際には別の方法でこれを行う方法がわかりません。szResults
タイプがchar *
多すぎて、これを変更することはできません!