Laden...

C#-Assembly in unmanaged C++ - Stackoverflow

Erstellt von bredator vor 12 Jahren Letzter Beitrag vor 12 Jahren 984 Views
B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 12 Jahren
C#-Assembly in unmanaged C++ - Stackoverflow

Vorab einige Infos, wie das erstellte Zeugs aussieht, und was es tun soll:
Es existiert ein sehr großes Programm, welches in C++ geschrieben wurde und seine Funktion erfüllt. Bisher zumindest. Jetzt sollte eine Funktion des Programms massiv überarbeitet und erweitert werden, was meine Aufgabe wurde. Diese Funktion greift auf eine Access-Datenbank zu, holt sich dort meist ein paar tausend Datensätze ab und gibt diese in entsprechender Form als xml aus. Das Ganze funktioniert für sich allein wunderbar - getestet habe ich alles als .exe, allerdings soll daraus eine .dll werden, welche im großen Programm (unmanaged) genutzt und aufgerufen wird. Das Aufrufen funktioniert soweit auch, allerdings fliegt er mir mitten in der .NET-Assembly beim füllen der Tables im DataSet mit einem Stackoverflow raus. Warum, das weiss ich nicht. Abfangen von StackoverflowException funktioniert leider nicht - er läuft in den try-Block und fliegt dann dort mit Stackoverflow weg. Ich hoffe, dass mir hier jemand helfen kann bzw. jemand eine Idee hat, woran das liegen könnte. Wie gesagt, für sich allein läuft die Assembly fehlerfrei und macht genau das, was sie soll (auch mit großen Datenmengen -> xml-Exporte mit teilweise 35-40 MB)
verwendetes Datenbanksystem: Access 97

Umgesetzt habe ich das Holen der Datensätze in C# wie folgt:

namespace AdasExport
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class AbExport()
    {
        public void writeData(int iAnbieter, int iStufe, int iDatumStart, int iDatumEnde)
       { 
        private DataSet dataSet = new DataSet();
        private OleDbConnection oledbConnection = new OleDbConnection();
        private OleDbCommand oledbSelectCommand = new OleDbCommand();
        private OleDbDataAdapter oledbDataAdapter = new OleDbDataAdapter();
        
        oledbConnection.ConnectionString = @"Data Source = TmpAbda.mdb;" + "Provider = Microsoft.Jet.OLEDB.4.0;";
        dataSet.Tables.Add()    //wird 8 mal ausgeführt, da ich 8 Tables benötige
        try
                {
                    label.Text = "Datenbanken werden gelesen...";
                    label.Refresh();
                    proBar.Value = 0;
                    int iSchrittweite = 142;

                    fillDiversTable();
                    proBar.Value += iSchrittweite;

                    fillLagerTable();             ----> hier fliegt er raus
                    proBar.Value += iSchrittweite;

                    fillLieferungTable();
                    proBar.Value += iSchrittweite;

                    fillGrosshaendlerTable();
                    proBar.Value += iSchrittweite;
                }
       }
//Hier sind natürlich noch viele weitere Funktionen, diese werden zu dem Zeitpunkt aber noch gar nicht angesprungen.

Die Funktion, in der er mir den Stackoverflow erzeugt, sieht so aus:

private void fillLagerTable()
        {
            oledbSelectCommand = oledbConnection.CreateCommand();
            oledbSelectCommand.CommandText = @"SELECT Lager.diPzn, Lager.iLagNr, Lager.diSpezVk FROM Lager;";
            oledbDataAdapter.SelectCommand = oledbSelectCommand;
            try
            {
                oledbDataAdapter.Fill(dataSet.Tables[3]);
            }
            catch (Exception ex)
            {
                writeFehlerlog(ex);
            }

            oledbSelectCommand = oledbConnection.CreateCommand();
            oledbSelectCommand.CommandText = @"SELECT LagerOrt.iLagNr, LagerOrt.strBezeich FROM LagerOrt ORDER BY iLagNr;";
            oledbDataAdapter.SelectCommand = oledbSelectCommand;
            try
            {
                oledbDataAdapter.Fill(dataSet.Tables[4]);      // An dieser Stelle tritt der Stackoverflow auf
            }
            catch (Exception ex)
            {
                writeFehlerlog(ex);
            }
        }

Offenbar führt er also einige Fill-Befehle aus und anscheinend geht ihm da irgendwann der Platz aus. Kommentiere ich den Aufruf der Funktion aus, dann fliegt er mir bei der nächsten raus mit derselben Meldung.

In den Projektoptionen habe ich den Haken bei "Für COM-Interop registrieren" gesetzt, was ja benötigt wird, um die Assembly überhaupt aus unmanaged Code aufzurufen. Hier wird mir dann eine .tlb erstellt, welche ich, zusammen mit der .dll, ins Verzeichnis meiner unmanaged Anwendung kopiere.

Im unmanaged Code gehe ich dann wie folgt vor:

#import "AdasExport.tlb" raw_interfaces_only

void PAnVive::StartViveTransfer(BOOL bManuell)
{	
	AbExport::_AbExport *pptr;
	CoInitialize(NULL);
	GUID dwTest = __uuidof(AbExport::AbExport);
	AbExport::_AbExportPtr Class1Ptr(dwTest);
	pptr = Class1Ptr;
	pptr->writeData_2(1,3,20100601, 20101230);      //Stackoverflow innerhalb Assembly
}

writeData_2 wird die public-Funktion in C++ genannt, die in C# writeData mit 4 Aufrufparametern heißt. Von dieser existiert noch eine mit 3 Parametern, deshalb wird sie in C++ als Nr. 2 aufgeführt.

Wie gesagt, sobald er in die Assembly springt, werden dort sogar ein paar .Fill-Anweisungen ausgeführt, aber ab einer bestimmten Menge scheint das nicht mehr zu wollen. Erklären kann ich es mir nicht so recht, da das Ding standalone ja funktioniert.

Woran könnte das liegen?

Gruß

5.658 Beiträge seit 2006
vor 12 Jahren

Eine StackOverflowException bekommt man ja meist, wenn irgendein rekursiver Methoden-Aufruf passiert. Was macht denn z.B. die writeFehlerlog-Methode? Kann es sonst irgendwo im Code zu unerwünschter Rekoursion kommen?

Weeks of programming can save you hours of planning

B
bredator Themenstarter:in
357 Beiträge seit 2010
vor 12 Jahren

Die WriteFehlerlog-Methode sieht so aus:

private void writeFehlerlog(Exception ex)
        {
            string dt = DateTime.Now.ToShortDateString() + "_" + DateTime.Now.Hour.ToString("00") + DateTime.Now.Minute.ToString("00") + DateTime.Now.Second.ToString("00");
            StreamWriter writer = new StreamWriter("fehler_" + dt + ".txt");
            writer.Write(ex.Message);
            writer.Write(ex.StackTrace);
            writer.Close();            
        }

Rekursive Funktionen sind nicht vorhanden.