C-Bibliothek liefert falschen int-Wert in C++/CLI [solved]



  • Ich greife auf eine Programmierschnittstelle eines Simulationstools zu. Dieses bietet eine statische C-Bibliothek für die Kommunikation. Damit ich diese in C# nutzen kann, schreibe ich einen Wrapper in C++/CLI.

    An manchen Stellen werden falsche int-Werte zurückgegeben. Rufe ich die gleiche Funktion in unmanaged Code auf, funktionieren sie jedoch einwandfrei:

    static int ApocGetQuantCount ()
    	 {
    		 // Returns -13
    		 return ::ApocGetQuantCount(srv);
    	 }
    

    -13 ist ein falscher Wert.

    Zum Test habe ich eine unmanaged DLL geschrieben. Der gleiche Aufruf:

    DLL int Test ()
    	{
    		// Returns 1577
                    return ApocGetQuantCount(Srv);
    	}
    

    1577 ist der richtige Wert. Interessanterweise geben andere Funktionen die korrekten Integer Werte zurück. Gibt es irgendeine Methode den Aufruf aus C++/CLI genauso ausführen zu lassen wie aus dem unmanaged Code? Kann ich in irgendeiner Form "marshallen"?



  • Integer werden nicht marshalled da sie blittable sind.

    Was mit aufgefallen ist: Du verwendest einmal "srv" und einmal "Srv". Ändert das was ?

    Ansonsten müsstest du etwas mehr Code zeigen, irgendwas stimmt an deinem Wrapper nicht.



  • DarkShadow44 schrieb:

    Was mit aufgefallen ist: Du verwendest einmal "srv" und einmal "Srv". Ändert das was ?

    Nein, ich hab den Handle einfach in dem Testprogramm "Srv" genannt, aber es ist jedesmal der gleiche Handle und es sind ja zwei unterschiedliche Programme...

    DarkShadow44 schrieb:

    Ansonsten müsstest du etwas mehr Code zeigen, irgendwas stimmt an deinem Wrapper nicht.

    Es gibt hier nicht mehr Code, die Funktion die aufgerufen wird ist in der statischen Bibliothek des Herstellers.

    Hier die Definition im Header:

    int ApocGetQuantCount (tApoSid sid);
    

    Der gleiche Funktionsaufruf liefert in C++/CLI -13 (falsch) und in C++ 1577 (richtig). Die Werte habe ich mir auf der Konsole ausgeben lassen und im Debugger geprüft.

    Irgendwas muss C++/CLI hier anders machen als C++.



  • Ok, aber irgendwie berechnet das Programm ja diese Zahl. Sicher dass du die Werte dafür richtig übergeben hast ?

    Irgendwie weiß ich grad nicht wonach ich fragen soll, ist einfacher wenn man das selber debuggen kann..
    Weil irgendwo kommt da ja ein falscher Wert rein, aber daran dass es C++/CLI statt C++ ist kann es eigentlich nicht liegen.

    Was für eine Bibliothek verwendest du denn ?
    Kannst du für beide Möglichkeiten mal ein kompilierbares Minimalbeispiel machen ?



  • Hallo vlow,

    eine C-Bibliothek kann man aber auch mittels des DllImport-Attributes direkt von C# aus nutzen (dafür alleine bräuchtest du also keinen C++/CLI Wrapper).
    Stichwort: P/Invoke



  • DarkShadow44 schrieb:

    Ok, aber irgendwie berechnet das Programm ja diese Zahl. Sicher dass du die Werte dafür richtig übergeben hast ?

    Das Programm ruft aus der statischen Bibliothek ab, wie viele Parameter der Server zur Verfügung stellt. Die Sequenz, die den ServerHandle abruft ist in C++/CLI und C++ die gleiche, auch der zurückgegebene ServerHandle ist identisch. Bis zum Aufruf der Funktion auf der statischen Lib sind alle Werte gleich.

    DarkShadow44 schrieb:

    Irgendwie weiß ich grad nicht wonach ich fragen soll, ist einfacher wenn man das selber debuggen kann..
    Weil irgendwo kommt da ja ein falscher Wert rein, aber daran dass es C++/CLI statt C++ ist kann es eigentlich nicht liegen.

    Genau das wundert mich auch, bisher hatte ich mit int-Werten aus C++ statischen Bibliotheken nie Probleme in C++/CLI.

    DarkShadow44 schrieb:

    Was für eine Bibliothek verwendest du denn ?
    Kannst du für beide Möglichkeiten mal ein kompilierbares Minimalbeispiel machen ?

    Es geht um den IPG CarMaker (APO-Schnittstelle). Da man diese Software zum testen benötigt, kann ich da leider kein ausführbares Beispiel dazu machen 😞

    Th69 schrieb:

    eine C-Bibliothek kann man aber auch mittels des DllImport-Attributes direkt von C# aus nutzen (dafür alleine bräuchtest du also keinen C++/CLI Wrapper).
    Stichwort: P/Invoke

    Danke 🙂 Aber diese Methode kenne ich schon, so funktioniert das aktuelle System. Davon wollen wir weg, es gab die Anforderung den Wrapper in C++/CLI zu schreiben, da einige spezielle Funktionen der statischen Bibliothek sich über Pinvoke nicht realisieren ließen und die Bibliothek in C# als Managed-Klassenbibliothek eingebunden werden soll.



  • So eine Wrapper-DLL kann auch gemischt sein. Normalerweise fange ich mit einem nativen DLL Projekt an und setze nur für Teile davon /clr und lege für den managed Teil eigene vorkompilierte Header an.

    Die Frage ist, welchen Grund gibt es, die statische Bibliothek aus managed Code aufzurufen ? Auch wenn ich noch nie gehört habe, dass es da mit int Parametern Probleme gibt. Wenn man sie im unmanaged Teil der DLL lädt, umgeht man das Problem zumindest.



  • Vielen Dank für die Hilfe, Ihr habt mich in die richtige Richtung gestoßen: Die C++/CLI Binary war aus irgendeinem Grund ein wenig schneller im abrufen der Information als die C++ Binary. Der Server war noch nicht bereit und hat deshalb den Bogus-Wert zurückgegeben. Eine kurze Zwangspause vor dem Aufruf hat das Problem gelöst!


Log in to reply