C++/CLI Wrapper für C++ unter C#



  • Guten Tag zusammen,

    erstmal hoffe ich, dass der Header einigermaßen verständlich ist und klar macht, worauf ich hinaus will, aber zur Sicherheit hier nochmal eine Beschreibung:

    Ich habe C++ Librarys, die ich gerne unter C# benutzen würde. Deshalb habe ich mich an C++/CLI gesetzt und plane, meinen Originalcode zu wrappen. Erstmal habe ich ein kleines Beispiel aufgesetzt:
    Test.hpp

    using namespace System;
    
    namespace Wrapper
    {
        public ref class TestClass
        {
        public:
            TestClass();
    
            static void Test();
        };
    }
    

    Test.cpp

    #include "Test.h"
    
    void Wrapper::TestClass::Test()
    {
        Console::WriteLine("Test");
    }
    
    Wrapper::TestClass::TestClass()
    {
        Console::WriteLine("Ctor");
    }
    

    Der ganze Quatsch wird mit VS8 und /clr kompiliert und in eine DLL rausgeschmissen. Unter C# dann wird das Projekt referenziert, benutzt, läuft.

    Jetzt erweitere ich das Beispiel um das Wrappen meiner Librarys, indem ich gegen sie linke und für ein Objekt eine Wrapperklasse geschrieben habe:

    Object.hpp

    #pragma once
    
    #include "MyObject.hpp" // Der Header der Library
    
    public ref class Object
    {
    public:
        Object(void);
    private:
        MyObject* obj;
    };
    

    Object.cpp

    #include "Object.hpp"
    
    Object::Object(void)
    {
        this->obj= new MyObject();
    }
    

    Unter C# greife ich jetzt also auf die MyObject-Klasse zu, kompiliere den Quatsch und führe das Programm erneut aus.

    Jetzt bricht das Programm beim Laden der DLL (sprich beim ersten Zugriff auf MyObject ODER Test) ab und schmeißt eine FileNotFoundException (Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E))

    Die DLL liegt immernoch am richtigen Platz und es hat sich nichts geändert, außer dass ich jetzt auch Native Code in meine DLL packe. Aber gerade weil es gemischter Code ist, benutze ich ja auch /clr und nicht z.B. /clr:pure.

    Ich bin etwas ratlos und hoffe, dass mir jemand helfen kann. Google konnte es in mehreren Anläufen nicht.

    Nochmal zur Info: Ich benutze VS8, sowohl für C++, C++/CLI als auch C#. Es ist alles in Debug gebuildet (Release bringt aber das gleiche Ergebnis) und auch die Prozessoren sind angeglichen.

    Vielen Dank fürs Lesen und ansonsten einen schönen Tag noch. 🙂



  • Du hast vermutlich ein x64 Rechner und bis 2008 wird per Default als TargetPlatform "Any CPU" gesetzt. D.h. Deine C# App läuft als x64 und kann somit dann nicht meher die x86 DLL Deiner C++/CLI Assembly laden...

    Fazit: Stelle die App auf x86 als Platform um, dann geht es...

    Oder erstelle zwei C++/CLI DLLs; eine für x86 und eine für x64... ist aber auch sehr unschön...



  • Jochen Kalmbach schrieb:

    Du hast vermutlich ein x64 Rechner und bis 2008 wird per Default als TargetPlatform "Any CPU" gesetzt. D.h. Deine C# App läuft als x64 und kann somit dann nicht meher die x86 DLL Deiner C++/CLI Assembly laden...

    Fazit: Stelle die App auf x86 als Platform um, dann geht es...

    Oder erstelle zwei C++/CLI DLLs; eine für x86 und eine für x64... ist aber auch sehr unschön...

    Bonzy schrieb:

    Nochmal zur Info: Ich benutze VS8, sowohl für C++, C++/CLI als auch C#. Es ist alles in Debug gebuildet (Release bringt aber das gleiche Ergebnis) und auch die Prozessoren sind angeglichen.

    Eventuell war es unverständlich ausgedrückt, aber ich habe bereits alles auf 32Bit umgestellt. Übrigens kommt es in diesem Fall eher zu einer BadImageFormatException mit der Info, dass das Format nicht stimmt.



  • Kannst du mal testweise

    #include "MyObject.hpp" // Der Header der Library
    

    weglassen und eine Dummyklasse

    class MyObject
    {
    public:
      MyObject() 
      {}
    };
    

    statt dessen verwenden ?

    Kommt der Fehler dann auch ?



  • nn schrieb:

    Kannst du mal testweise

    #include "MyObject.hpp" // Der Header der Library
    

    weglassen und eine Dummyklasse

    class MyObject
    {
    public:
      MyObject() 
      {}
    };
    

    statt dessen verwenden ?

    Kommt der Fehler dann auch ?

    Nein, dann bleibt der Fehler aus. Hast du einen Ansatz, was ich mit diesem Wissen machen kann?



  • Bonzy schrieb:

    Hast du einen Ansatz, was ich mit diesem Wissen machen kann?

    Ich würde mal vermuten, er sucht beim Anlegen von MyObject irgendeine abhängige DLL ...



  • nn schrieb:

    Bonzy schrieb:

    Hast du einen Ansatz, was ich mit diesem Wissen machen kann?

    Ich würde mal vermuten, er sucht beim Anlegen von MyObject irgendeine abhängige DLL ...

    Für das Erstellen von MyObject werden aber keine DLLs benötigt. Es werden lediglich statische Bibliotheken direkt in die CLI-DLL gelinkt, die werden bei Verwendung des Objects im Wrapper auch hinzugepackt, merkbar an der Größe und dem Dependency Walker.



  • Kannst du an die Stelle mit dem new MyObject einen Breakpoint setzen und dann da hineinsteppen ?

    Edit:

    Und mach die Klammen da weg

    obj = new MyObject;
    


  • nn schrieb:

    Kannst du an die Stelle mit dem new MyObject einen Breakpoint setzen und dann da hineinsteppen ?

    Edit:

    Und mach die Klammen da weg

    obj = new MyObject;
    

    Sind die Klammern schlechter Stil? Ich habe noch nie einen Konstruktor ohne Klammern benutzt. Ist es eindeutiger, den leeren Konstruktor auf diese Art aufzurufen?

    Zum Thema: Ich kann leider keinen Breakpoint setzen, sobald ich nur versuche in die Methode zu springen, in der ich auf die DLL zugreife, wird es nichts.

    Allerdings bin ich gerade nochmal anders rangegangen: Ich habe versucht, mein Objekt direkt in dem CLI Projekt auszuführen sprich es in eine Konsolenanwendung umgewandelt und schlicht in der Main drauf zugegriffen. Dabei stieß ich dann auf die DLL, die scheinbar fehlt und mir den ganzen Ärger einbrockt: vcompd.dll. Ich bin leider nicht der Entwickler der DLL und mir war bisher nicht bekannt, dass OpenMP benutzt wird, deshalb werde ich das jetzt mal nachinstallieren und hoffen. 🙂



  • Bonzy schrieb:

    Sind die Klammern schlechter Stil?

    Hat wahrscheinlich nichts mit diesem Problem zu tun. Aber irgendwo hatte ich schon in C++ Probleme, mit der Angewohnheit die leeren Klammern so zu schreiben wie bei C#.



  • nn schrieb:

    Kannst du an die Stelle mit dem new MyObject einen Breakpoint setzen und dann da hineinsteppen ?

    Edit:

    Und mach die Klammen da weg

    obj = new MyObject;
    

    Ich würd die Klammern lassen - bei POD Typen spielts nämlich eine Rolle ob da welche sind oder nicht.



  • Nachinstallieren von OpenMP/includen des Headers hat letztlich zur Lösung geführt. Danke für die Denkanstöße! 🙂


Anmelden zum Antworten