Hallo,
ich versuche eine in C++ erstellte DLL in C# einzubinden und darin eine Funktion aufzurufen.
Ich erhalte aber die Exception "Unable to find an entry point named 'GetValue' in DLL 'xyzdll.dll'.
Einen EntryPoint bei DllImport brauche ich ja nicht, da beide Funktionen (DLL und C#) gleich lauten.
Aber wie müsste es korrekt lauten?
//Bibliotheksfunktion in "xyzdll.dll"
XYZDLL_API int GetValue( int *pValue );
public partial class Form1 : Form
{
[DllImport("xyzdll.dll")]
static extern int GetValue( out int pBrightness );
private void button1_Click(object sender, EventArgs e)
{
int value = 0;
GetValue(out value);
}
}
1.) genaue fehlermeldung: entrypoint not found oder dll not found?
2.) betrachte die dll im dependency walker (depends.exe) und kopier den exakten namen (c++ dekoriert namen gerne)
3.) wenn name garnicht in der liste auftaucht: in deiner dll muss die funktion als __declspec(dllexport) gekennzeichnet sein
4.) du kannnst dir das ganze auch sparen, wenn du c++ interop machst (c++ für clr compilierst)
Danke schon mal für die Hinweise.
zu 1.) entrypoint not found
zu 2.) dekorierter Name: ?GetValue@@YAHPAH@Z --> ist keine gültige Syntax
Undekoriert lautet der Name wie im ersten Posting: int GetValue( int *)
Es gibt noch eine C-Funktion: C_GetValue. Bei deren Aufruf kommt aber der Fehler "PInvokeStackImbalance was detected".
zu 4.) Die DLL ist von einem Drittanbieter. Aber ich komme vielleicht an den Code ran.
ekorierter Name: ?GetValue@@YAHPAH@Z --> ist keine gültige Syntax
Damit hast du rausgefunden, dass folgendes nicht stimmt:
Einen EntryPoint bei DllImport brauche ich ja nicht, da beide Funktionen (DLL und C#) gleich lauten.
Damit wäre dein Problem sogut wie gelöst:
[DllImport("dllname.dll",EntryPoint="?GetValue@@YAHPAH@Z")]
....
Es gibt noch eine C-Funktion: C_GetValue. Bei deren Aufruf kommt aber der Fehler "PInvokeStackImbalance was detected".
Das kann vier mögliche Gründe haben:
a) Parameterzahl stimmt nicht überein
b) Callingconvention stimmt nicht überein. Diese lässt sich im dllimport-attribut explizit angeben. Da die funktion keine Dekoration hat, ist es höchstwahrscheinlich cdecl
c) Falsche typen bzw falsche Umwandlung (Marshaling)
d) Fehlerhafter c-code (Es ist schon eine Kunst derartige Fehler unabsichtlich so einzubauen, dass sie immer auftreten.)
Das Name-Mangling von C++ passt nicht mit dem von C# zusammen da die Funktion, wie du ja schon gesehen hast in C++ nicht einfach GetValue heißt sondern noch etwas hinzugefügt wird und das findet C# dann nicht.
Wenn du an den Code der DLL rankommst kannst du dort für die Funktion auch C-Linkage erzwingen, das sollte das Problem auch lösen:
extern "C" __declspec(dllexport) int GetValue( int *pValue );
Nana im c#code einfach den entrypoint explizit anzugeben ist im konkreten fall sicherlich einfacher.
Ich habe aber auch schon von deinem extern "C"-trick gelesen. Allerdings hat er bei mir nicht wirklich funktioniert, als ich den probiert hatte. Hat zu haufenweise unerklärlicher fehler geführt.
Wenn ich die DLL selber schreibe, mach ichs grundsätzlich so, Fehler hat das bei mir noch nie produziert.
Bei DLLs von Drittanbietern geht es sicher nicht ganz so einfach, da ist dein Weg bestimmt der Bessere.