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
Hallo cosmo0815,
statt char* String verwenden. Um die Umsetzung kümmert sich .NET.
herbivore
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
Schau dir einfach mal an was für Properties der SaveFileDialog bietet.
Baka wa shinanakya naoranai.
Mein XING Profil.
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
Hallo cosmo0815,
Kann mir da einer ein Tip geben warum das nicht klappt.
geht es genauer?
herbivore
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)
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
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.
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
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
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.
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
Tja, die .NET Deklaration ist korrekt. Jetzt wäre es an der Zeit die DLL zu debuggen.
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.
Wo übergibts du denn einen Delegaten an eine unmanaged Funktion?
hallo,
schon mal den stringbuilder versucht? hatte das selbe problem und hab statt dem string einfach einen stringbuilder übergeben. und vergiss die capacity nicht
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.