Witam,
mam dwa problemy z wywołaniem funkcji C# z C++ i C++ z C#.
Pierwszy problem to: "An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
Additional information: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona." Zapomniałem dodać że ten problem występuje tylko w trybie debug, w trybie release działa bez problemu. Kod:
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace TestEngine
{
public struct TestClass
{
public delegate void Test();
public int liczba;
public Test test;
}
public class CppWrapper<A>
{
private A reference;
private unsafe void* pointer;
public unsafe CppWrapper(void* classFactoryPointer)
{
reference = Marshal.PtrToStructure<A>((IntPtr)classFactoryPointer);
unsafe
{
pointer = Marshal.AllocHGlobal(Marshal.SizeOf(reference)).ToPointer();
Marshal.StructureToPtr(reference, (IntPtr)pointer, false);
}
}
public A GetReference()
{
return reference;
}
public IntPtr GetIntPointer()
{
unsafe
{
return (IntPtr)pointer;
}
}
public unsafe void* GetPointer()
{
return pointer;
}
}
public struct Data
{
public int tekst;
}
class Program
{
private unsafe delegate void CSharpCallback(void* data);
[DllImport("TestEngine_Core.dll")]
private static extern void Print(string text);
[DllImport("TestEngine_Core.dll")]
private unsafe static extern void* CreateTestClass();
[DllImport("TestEngine_Core.dll")]
private unsafe static extern void ChangeLiczba(void* test, int liczba);
[DllImport("TestEngine_Core.dll")]
private unsafe static extern void SetCSharpCallback(void* test, CSharpCallback cs);
[DllImport("TestEngine_Core.dll")]
private unsafe static extern void CallCSharpCallback(void* test);
private unsafe static void lol(void* data)
{
CppWrapper<Data> lol = new CppWrapper<Data>(data);
System.Console.WriteLine("ee " + lol.GetReference().tekst);
}
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
unsafe
{
CppWrapper<TestClass> test = new CppWrapper<TestClass>(CreateTestClass());
ChangeLiczba(test.GetPointer(), i);
SetCSharpCallback(test.GetPointer(), lol);
//CallCSharpCallback(test.GetPointer());
test.GetReference().test();
}
}
while (true) ;
}
}
}
exports.h
#pragma once
class TestClass;
#define EXPORT extern "C" __declspec(dllexport)
#define CSHARP_CALLBACK void(__stdcall *csCallback)(void* data)
EXPORT void _stdcall Print(const char* text);
EXPORT TestClass* CreateTestClass();
EXPORT void _stdcall ChangeLiczba(TestClass* test, int liczba);
EXPORT void _stdcall SetCSharpCallback(TestClass* test, CSHARP_CALLBACK);
EXPORT void _stdcall CallCSharpCallback(TestClass* test);
exports.cpp
#include "exports.h"
#include <iostream>
#include "testclass.h"
void _stdcall Print(const char* text)
{
std::cout << text << std::endl;
}
TestClass* CreateTestClass()
{
return new TestClass();
}
void _stdcall ChangeLiczba(TestClass* test, int liczba)
{
test->ChangeLiczba(liczba);
}
struct Data
{
int tekst;
};
void _stdcall SetCSharpCallback(TestClass* test, CSHARP_CALLBACK)
{
test->cs = csCallback;
test->cs(new Data{ test->liczba });
}
void _stdcall CallCSharpCallback(TestClass* test)
{
test->cs(new Data{ test->liczba });
}
testclass.h
#pragma once
#include <iostream>
class TestClass
{
public:
typedef void(_stdcall *CSharpCallback)(void* data);
typedef void(TestClass::*Test)();
private:
public:
TestClass();
~TestClass();
int liczba;
Test test;
CSharpCallback cs;
void ChangeLiczba(int liczba);
void TestFunc();
};
testclass.cpp
#include "testclass.h"
TestClass::TestClass()
{
liczba = 0;
test = &TestClass::TestFunc;
}
TestClass::~TestClass()
{
}
void TestClass::ChangeLiczba(int liczba)
{
this->liczba = liczba;
}
void TestClass::TestFunc()
{
std::cout << "Call from c# to c++" << std::endl;
}
Drugi problem to: "Exception thrown at 0x7797E3BE (ntdll.dll) in TestEngine.exe: 0xC0000005: Access violation reading location 0x0853A883. If there is a handler for this exception, the program may be safely continued."
Występuje po usunięciu komentarza przy "CallCSharpCallback(test.GetPointer());" Program.cs linia 96 i dodaniu komentarza przy "test->cs(new Data{ test->liczba });" exports.cpp linia 30
Co mogłoby być problemem, bo w ogóle nie wiem o co chodzi z tymi errorami. Zmagam się z nimi już jakiś czas i dalej nie znalazłem rozwiązania, czytałem że bardzo ciężko jest zdiagnozować tego typu problem.
EDIT:
Dobra, rozwiązanie problemu było bardzo proste, a przyczyna bardzo głupia: w Program.cs wystarczyło dodać do struktury "TestClass" zmienną "public CSharpCallback csharpCallback;". Klasa z C++ różniła się od tej z C# i dlatego był problem z alokacją odpowiedniej ilości pamięci.