Laden...

Problem eine Funktion in einer DLL anzusprechen

Erstellt von cosmo0815 vor 17 Jahren Letzter Beitrag vor 17 Jahren 4.393 Views
C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren
Problem eine Funktion in einer DLL anzusprechen

Hallo Ihr ich habe ein Problem eine Funktion in einer DLL anzusprechen.
Ich möchte gerne mit C# eine C Funktion in einer DLL ansprechen.

Die Funktion sieht folgendermaßen aus:
################################################################
int SaveDB( const char * fileName)

Parameters
fileName - Null-terminated string thats specifies the fileName

Return Values
Succes 0
################################################################

Mir ist klar das ich die Funktion über DLLImport bekannt muss, was ich gemacht habe. Mir ist nur nicht klar wie ich das mit dem Zeiger machen soll unter C#.

Kann mir da vielleicht jemand helfen.

Helge

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo cosmo0815,

statt char* String verwenden. Um die Umsetzung kümmert sich .NET.

herbivore

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Original von herbivore
Hallo cosmo0815,

statt char* String verwenden. Um die Umsetzung kümmert sich .NET.

herbivore

Ok sowas dachte ich mir schon!
Aber mein Problem ist jetzt noch wie das mit einem SaveFileDialog löse.
Das ich der Funktion den String übergebe welcher den FileName bezeichnet.

Helge

6.862 Beiträge seit 2003
vor 17 Jahren

Schau dir einfach mal an was für Properties der SaveFileDialog bietet.

Baka wa shinanakya naoranai.

Mein XING Profil.

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Hallo Ihr ich habe ein Problem eine Funktion in einer DLL anzusprechen.
Ich möchte gerne mit C# eine C Funktion in einer DLL ansprechen.

Die Funktion sieht folgendermaßen aus:
################################################################
int SaveDB( const char * fileName)

Parameters
fileName - Null-terminated string thats specifies the fileName
Return Values
Succes 0
################################################################

Ich habe die Funktion dann folgendermassen eingebunden.
Anstatt char * fileName habe ich dann string fileName verwendet.


[DllImport("DB_SDK.dll",
                    CharSet = CharSet.Auto,
                    EntryPoint = "SaveDB")]
public static extern int SaveDB(string fileName);

Ich habe dann versucht die Funktion so aufzurufen.


private void saveDB_Click(object sender, EventArgs e)
        {
           
            
           
            if (this.saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                
                int result = SaveDB(saveFileDialog1.FileName);

			}
		}

Kann mir da einer ein Tip geben warum das nicht klappt.

Helge

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo cosmo0815,

Kann mir da einer ein Tip geben warum das nicht klappt.

geht es genauer?

herbivore

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Es kommt eine Fehlermeldung. Unbehandelte Ausnahme in der Anwedung.

Auszug der Fehlermeldung:

Informationen über das Aufrufen von JIT-Debuggen
anstelle dieses Dialogfelds finden Sie am Ende dieser Meldung.

************** Ausnahmetext **************
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.
bei Fingercheck.API.SaveDB(String fileName)
bei Fingercheck.Form1.readTemp_Click(Object sender, EventArgs e)
bei System.Windows.Forms.Control.OnClick(EventArgs e)
bei System.Windows.Forms.Button.OnClick(EventArgs e)
bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
bei System.Windows.Forms.Button.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Hallo Ihr ich habe ein Codebespiel gefunden wie die Funktion unter C++ verwendet wird.


CFileDialog* fileDialog = new CFileDialog( TRUE, ".db", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CMainFrame::s_TemplateDBFilter, NULL );

	if( fileDialog->DoModal() == IDOK )
	{
		int result = SaveDB( fileDialog->GetPathName() );

	}

Kann mir da jetzt vielleicht jemand helfen wie ich das mit C# lösen könnte?

Helge

6.862 Beiträge seit 2003
vor 17 Jahren

Kenn mich damit auch net genau aus, aber kann sein das mit dem Pfadnamen vielleicht was falsch ist? Weil c# hat ja durchgehend Unicode und das falsch gemarshalled wird auf den C++ String.

Baka wa shinanakya naoranai.

Mein XING Profil.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo cosmo0815,

Kenn mich damit auch net genau aus, aber kann sein, dass die CharSet-Einstellung falsch ist?

Im Grund sollte es nämlich so gehen (also den String einfach übergeben).

herbivore

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Hallo nochmal ich bekomme immer diese Fehlermeldung.

Es kommt eine Fehlermeldung. Unbehandelte Ausnahme in der Anwedung.

Klicken Sie Weiter oder Beenden.

Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben.
Dies ist häufig ein Hinweis darauf, dfas anderer Süpeicher beschädigt ist.

Helge

S
8.746 Beiträge seit 2005
vor 17 Jahren

Eine "unbehandelte Ausnahme" mit "Schutzverletzung" ist ein sicheres Zeichen, dass die Funktion in der DLL abstürzt.

Leider lieferst du uns ja keinen Auszug aus der .h-Datei, die klären würde, mit welchen Charset die C++-DLL arbeitet. Ich vermute aber, dass es sich hier um ANSI handelt. .NET arbeitet aber per Default mit Unicode.

Du musst daher das Chaset von Auto (Unicode) auf Ansi umstellen.

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Hallo ihr,

also in der API.h steht das folgende: (Auszug)

__declspec( dllexport ) RET_CODE SaveDB( const char* fileName );

Ich habe das schon getestete CharSet.Ansi zu setzen.

[DllImport("DB_SDK.dll",
CharSet = CharSet.Ansi,
EntryPoint = "SaveDB")]
public static extern int SaveDB(string fileName);

Das hat aber nichts gebracht.

Helge

S
8.746 Beiträge seit 2005
vor 17 Jahren

Tja, die .NET Deklaration ist korrekt. Jetzt wäre es an der Zeit die DLL zu debuggen.

C
cosmo0815 Themenstarter:in
8 Beiträge seit 2006
vor 17 Jahren

Hallo ich gerade mal ein Debug gemacht und das sagt mir nun das


private void readTemp_Click(object sender, EventArgs e)
        {
           
            SaveFileDialog dlgSave = new SaveFileDialog();
            dlgSave.Filter = "Data (*.dat)|*.dat|Alle Dateien|*.*";
            if (dlgSave.ShowDialog() == DialogResult.OK)
            {
                
                int result = API.UF_SaveDB(dlgSave.FileName);

            }
            
        }
//Beim Debuggen kommt bei dieser Funktion.  
//Ein Fenster mit der Mitteilung "CallbackOnCollectedDelegate wurde erkannt.

Für den von der Garbage Collection gesammelten Delegaten vom Typ "Fingercheck!Fingercheck.DataCallback::Invoke" wurde ein Rückruf durchgeführt. Dies kann Anwendungsabstürze, Datenbeschädigung und -verlust zur Folge haben. Beim Übergeben von Delegaten an nicht verwalteten Code müssen die Delegaten von der verwalteten Anwendung beibehalten werden, bis sichergestellt ist, dass sie nie aufgerufen werden.

S
8.746 Beiträge seit 2005
vor 17 Jahren

Wo übergibts du denn einen Delegaten an eine unmanaged Funktion?

G
11 Beiträge seit 2004
vor 17 Jahren

hallo,

schon mal den stringbuilder versucht? hatte das selbe problem und hab statt dem string einfach einen stringbuilder übergeben. und vergiss die capacity nicht

T
68 Beiträge seit 2006
vor 17 Jahren

hmm
ich kann mir ca. vorstellen warum du eine Fehlermeldung bekommst.
string ist in c# kein wirklicher typ. Sondern wird viel mehr als Objekt behandelt.
Das Problem ist das in c* ein Pointer auf eine Speicheradresse eines konstanten literals ist. Ein String ist meines wissen nach in c# kein konstanter literal. Und die speicherstruktur eines objektes und eines konstanten literals ist nun mal anderes und nicht 1:1 umsetzbar. (genauere Begründung geb ich gerne ist aber momentan nicht so relevant)

In C++ ist es möglich einen pointer auf ein c-array zeigen zu lassen. Daher könntest es mal so probieren.


char [] fname = dlgSave.fileName.ToCharArray();

// dann denn aufruf der methode mit fname 
...
int result = API.UF_SaveDB(fname);
...

Es ist nur eine Vermutung das das funktionieren könnte. sicher ist dies allerdings nicht. Sollte dennoch eine exception fliegen, liegt es nur daran, dass man in c# nicht wirklich mit pointern arbeiten kann.

S
8.746 Beiträge seit 2005
vor 17 Jahren

Hast du ne Fingerprint-Komponente im Programm?