• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed C# Unmanaged code

Object Storage Arubacloud
0 głosów
1,229 wizyt
pytanie zadane 16 listopada 2017 w C# przez MisterVento3 Użytkownik (830 p.)
zamknięte 16 listopada 2017 przez MisterVento3

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.

komentarz zamknięcia: Rozwiązanie problemu.

Podobne pytania

0 głosów
0 odpowiedzi 294 wizyt
pytanie zadane 7 lipca 2019 w C# przez KazikBozia Obywatel (1,600 p.)
0 głosów
0 odpowiedzi 127 wizyt
pytanie zadane 19 listopada 2017 w C# przez jankustosz1 Nałogowiec (35,880 p.)
0 głosów
0 odpowiedzi 2,113 wizyt

92,555 zapytań

141,402 odpowiedzi

319,543 komentarzy

61,939 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...