myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » System.AccessViolationException bei C++ dllimport in C#
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

System.AccessViolationException bei C++ dllimport in C#

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
tintenherz
myCSharp.de-Mitglied

Dabei seit: 22.10.2007
Beiträge: 4


tintenherz ist offline

System.AccessViolationException bei C++ dllimport in C#

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo und Guten Tag,

da dies mein erster Thread hier ist möchte ich mich als erstes bei Denjenigen, die Ihr Wissen hier kostenlos und uneigennützig weitergeben, bedanken.
Ich habe mir schon diverse Male hier einen Rat oder ein gutes Beispiel holen können.


Nun zu meiner Herausforderung:
Ich arbeite mit VS2005.
Ich benutze in einem C# Projekt eine C++ Dll (unmanaged Code).
Dllimport etc. soweit erfolgreich:

C#-Code:
[DllImport("ABSServicesud.dll", EntryPoint = "#6",
        ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool OpenDatabase();

Aufruf in C#:

C#-Code:
private void button1_Click(object sender, System.EventArgs e)
        {
            try
            {
                bool bRet = OpenDatabase();
                if (bRet)
               .......
            }
            catch (System.AccessViolationException x )
            {
                MessageBox.Show(x.ToString());
             }
        }

Methode in der C++ Dll:

C#-Code:
bool CPrintService::OpenDatabase()
{
    AfxMessageBox(_T("1"));

    CString strProvider            =_T("SQLOLEDB.1");    //Provider für ADO     -> z.B. "SQLOLEDB.1"
    CString strDataSource        =_T("SRV-SQL-TEST");        //Name des DB-Servers  -> z.B. "SRV-SQL-TEST"
    CString strPassword            =_T("Test-User");        //Passwort             -> z.B. "Test-User"
    CString strUserID            =_T("Test-User");            //Benutzerkennung      -> z.B. "Test-User"
    CString strInitialCatalog    =_T("APPLI");            //Name der DB          -> z.B. "APPLI"          
    CString strApplicationName    =_T("PrintService");
    AfxMessageBox(_T("2"));
    //ADO Connection String bauen
    CString strConnect=_T("");
    BuildConnectString(strProvider, strPassword, strUserID, strDataSource, strInitialCatalog, strApplicationName, strConnect );
    AfxMessageBox(_T("3"));
    try
    {
        TRY
        {
             m_Database.Open(strConnect);
        }
        CATCH(CDBException, e)
        {
            //TODO
            return false;
        }
        END_CATCH
    }
    catch (...) //catch any exception
    {
        AfxMessageBox(_T("4"));
        //TODO
        return false;
    }

Das m_Database Objekt ist von einer Frameworkklasse abgeleitet und gibt BOOL zurück.

Der Fehler tritt in der Zeile: "m_Database.Open(strConnect);" auf.
Fehlermeldung: "System.AccessViolationException: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist."

Ich laufe in keine der Fehlerbehandlungen in OpenDatabase() hinein, sondern die Fehlermeldung kommt aus der C#-Ebene.

Ich hoffe ich habe mich detailiert genug ausgedrückt und dennoch nicht zuviel Text geschrieben.
Mir gehen die Ideen aus an welcher Stellle ich den Fehler suchen soll und wäre daher für jeden Hinweis dankbar.
22.10.2007 14:27 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Der Fehler kommt aus der DLL. Debugge sie mal.
22.10.2007 14:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
tintenherz
myCSharp.de-Mitglied

Dabei seit: 22.10.2007
Beiträge: 4

Themenstarter Thema begonnen von tintenherz

tintenherz ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Danke svenson für den Hinweis.

Ich habe versucht die DLL zu debuggen was jedoch leider gescheitert ist.

Habe mich an folgende Anleitung gehalten:  http://groups.google.de/group/microsoft....03cf0ea31491cbd

Zusammenfassung:
- dafür gesorgt das die Application (C#) die Dll von dort läd wo das C++-Proj. sie
erstellt.
- Das C++-Proj. als Startprojekt festgelegt.
- C++-Proj.->Eigenschaften->Konfigurationseingenschaften->Debuggen->Befehl: Pfad
zu der Exe der Applikation (C#).

Die Dll wird zwar aufgerufen, jedoch ist kein Debugging möglich.

Sollte jemand eine andere Möglichkeit kennen würde ich mich über einen Hinweis freuen.
23.10.2007 15:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
tintenherz
myCSharp.de-Mitglied

Dabei seit: 22.10.2007
Beiträge: 4

Themenstarter Thema begonnen von tintenherz

tintenherz ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das Debuggen der Dll konnte ich inzwischen erfolgreich durchführen.

Lösung:
Sourcecode der Dll in das Projektverzeichniss kopieren und die Verweispfade löschen.
24.10.2007 13:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
tintenherz
myCSharp.de-Mitglied

Dabei seit: 22.10.2007
Beiträge: 4

Themenstarter Thema begonnen von tintenherz

tintenherz ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe ein leichteres Projekt erstellt in der Hoffnung das Jemand von Euch doch noch einen Vorschlag machen kann.

Mein Problem ist die Nutzung von nativen C++-Dll's aus C#, wobei ich die Methoden einer Dll per dllimport in C# importiert habe, diese C++-Dll jedoch weitere C++-Dll's inkludiert.

C#-Anwendung: Program.cs

C#-Code:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;




namespace WindowsApplication6
{
    ///
    /// Summary description for Form1.
    ///
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox textBox3;
        ///
        /// Required designer variable.
        ///
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        ///
        /// Clean up any resources being used.
        ///
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        ///
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        ///
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.label2 = new System.Windows.Forms.Label();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(64, 192);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(144, 64);
            this.button1.TabIndex = 0;
            this.button1.Text = "call sum";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(40, 120);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(72, 22);
            this.textBox1.TabIndex = 1;
            this.textBox1.Text = "2";
            //
            // label1
            //
            this.label1.Location = new System.Drawing.Point(128, 128);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(16, 16);
            this.label1.TabIndex = 2;
            this.label1.Text = "+";
            //
            // textBox2
            //
            this.textBox2.Location = new System.Drawing.Point(152, 120);
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(56, 22);
            this.textBox2.TabIndex = 3;
            this.textBox2.Text = "3";
            //
            // label2
            //
            this.label2.Location = new System.Drawing.Point(224, 120);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(24, 23);
            this.label2.TabIndex = 4;
            this.label2.Text = "=";
            //
            // textBox3
            //
            this.textBox3.Location = new System.Drawing.Point(248, 120);
            this.textBox3.Name = "textBox3";
            this.textBox3.Size = new System.Drawing.Size(112, 22);
            this.textBox3.TabIndex = 5;
            this.textBox3.Text = "5";
            //
            // Form1
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
            this.ClientSize = new System.Drawing.Size(576, 322);
            this.Controls.AddRange(new System.Windows.Forms.Control[] { this.textBox3, this.label2, this.textBox2, this.label1, this.textBox1, this.button1 });
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
        #endregion

        ///
        /// The main entry point for the application.
        ///
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }

        #region My Code
        #region Dll Imports
        #endregion

        #region Button Click Events

        [DllImport("TestDll1.dll", EntryPoint = "#7",
        ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Test1();

        [DllImport("TestDll1.dll", EntryPoint = "#8",
        ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int Test1_1();

        [DllImport("TestDll1.dll", EntryPoint = "#9",
        ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int TestInt1();

        private void button1_Click(object sender, System.EventArgs e)
        {
            //int nTestInt = TestInt1();  //Aufruf einer Methode aus Klasse1
            int nTest = Test1_1();      //indirekter Aufruf einer Methode aus Klasse2
            bool bTest = Test1();       //indirekter Aufruf einer Methode aus Klasse2

        }
        #endregion
        #endregion
    }
}

C++-Dll Nr. 1 (Klasse1.h) (Name des SubProjekt: TestDll1)
------------------------------
#ifndef __KLASSE1_H__
#define __KLASSE1_H__

#include "..\TestDll2\Klasse2.h"


// Klasse1.h : Header-Datei
//

class _declspec(dllexport) CKlasse1
{
// Konstruktion
public:
CKlasse1();
~CKlasse1();
BOOL Test1();
int Test1_1();
int TestInt1();

// Attribute
public:
CKlasse2 m_Klasse2;
CKlasse2 m_Klasse2_2;
};

/////////////////////////////////////////////////////////////////////////////

#endif // __KLASSE1_H__

C++-Dll Nr. 1 (Klasse1.cpp)
--------------------------------
// Klasse1.cpp: Implementierungsdatei
//
#include "stdafx.h"
#include "Klasse1.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CKlasse1

CKlasse1::CKlasse1()
{

}

CKlasse1::~CKlasse1()
{
}

BOOL CKlasse1::Test1()
{
return m_Klasse2.Test2(_T("Hallo"));
}

int CKlasse1::Test1_1()
{
return m_Klasse2_2.Test2_2(2, cool ;
}

int CKlasse1::TestInt1()
{
int a=2;
int b=9;

return a + b;
}


C++-Dll Nr. 2 (Klasse2.h) (Name des SubProjekt: TestDll2)
--------------------------------
#ifndef __KLASSE2_H__
#define __KLASSE2_H__


// Klasse2.h : Header-Datei
//

class __declspec( dllexport ) CKlasse2
{
// Konstruktion
public:
CKlasse2();
~CKlasse2();
BOOL Test2(CString strTest);
int Test2_2(int a, int b);

// Attribute
public:
CString m_strTest;
int m_nTest;
};

/////////////////////////////////////////////////////////////////////////////

#endif // __KLASSE1_H__


C++-Dll Nr. 2 (Klasse2.cpp)
--------------------------------
// Klasse2.cpp: Implementierungsdatei
//
#include "stdafx.h"
#include "Klasse2.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CKlasse2

CKlasse2::CKlasse2()
{
int m_nTest= 0;
}

CKlasse2::~CKlasse2()
{
}

BOOL CKlasse2::Test2(CString strTest)
{
m_strTest = strTest;

return TRUE;
}

int CKlasse2::Test2_2(int a, int b)
{
m_nTest = (a + b);
return m_nTest;
}


Ich gehe wie folgt vor:
-import der Methoden der "Klasse1" per dllimport
-Aufruf der Methoden der "Klasse1" aus der C#-Anwendung (int Test1_1())
-diese ruft Ihrerseits eine Methode der "Klasse2" über eine Membervariable der
"Klasse2" auf.
-der Aufruf der Methode der "Klasse2" funktioniert:

int CKlasse2::Test2_2(int a, int b)
{
m_nTest = (a + b);
return m_nTest;
}


jedoch schlägt die Zuweisung der Summe (a+b) an m_nTest fehlt mit dem Hinweis:
"System.AccessViolationException"
Zusätzliche Informationen: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

Tut mir leid für den langen Text. Ich hatte die Befürchtung das ich das Problem sonst nicht richtig erklären könnte und jemand sich die Mühe macht für eine Aufgabenstellung die auf einem Missverständnis beruht.

Achtung: sollte Jemand den Code kopieren. In der Klasse1.cpp ist eine "()" als Smiley interpretiert worden. Ich weis nicht wie sich da die Zwischenablage verhält.

Sollte jemand diesen ganzen Test gelesen haben und kann dennoch nicht weiterhelfen Danke ich zumidest für die Mühe.
24.10.2007 17:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Kommt es dir nicht komisch vor, dass du eine Methode (!) einer Klasse aufrufen kannst, ohne dass du irgendwo ein Objekt hast?

Suche mal "C++" in der Forumssuche und dir wirst einige Antworten auf deine Frage bekommen. Kurz gesagt: Es geht nur mit einiger Handarbeit und Einschränkungen um C++-Methoden aufzurufen.

Grundsätzlich sich C++-DLLs so ohne weiteres nur von C++ (und dem gleichen Compiler) aus aufrufbar.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von svenson am 24.10.2007 23:21.

24.10.2007 23:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 12 Jahre.
Der letzte Beitrag ist älter als 12 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 02.06.2020 08:22