DLL-Funktion aus C# aufrufen [gelöst]



  • Ist vermutlich eine dumme Frage, aber ich komme nicht mehr weiter:

    Ich habe folgenden C++-Code:

    bib.hpp:

    #define DLL __declspec(dllexport) 
    
    DLL int Func(int);
    

    bib.cpp

    #include "bib.hpp"
    
    int Func(int i)
    {
    	//Rein zu Testtzwecken
    	return i;
    }
    

    Mit

    cl /EHsc /LD bib.cpp
    

    kompiliere ich das zu einer DLL, und erhalte auch tatsächlich die Dateien bib.lib, bib.obj, bib.exp.

    Ich versuche dann in

    program.cs

    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace App
    {
    	public static class Program
    	{
    		[DllImport("bib.dll")]
            	public static extern int Func(int a);
    
    		public static void Main(String[] args)
    		{
    			Console.WriteLine("Test");
    			Console.WriteLine(Func(1));
    		}
    	}
    }
    

    Dies kompiliert mit

    csc program.cs
    

    auch fehlerfrei zu program.exe.

    Beim Ausführen erhalte ich jedoch folgende Ausnahme/Fehlermeldung:

    Unbehandelte Ausnahme: System.BadImageFormatException: Es wurde versucht, eine D
    atei mit einem falschen Format zu laden. (Ausnahme von HRESULT: 0x8007000B)
       bei App.Program.Func(Int32 a)
       bei App.Program.Main(String[] args)
    

    In Visual Studio lautet die Meldung/Ausnahme:

    Eine Ausnahme vom Typ "System.EntryPointNotFoundException" ist in suite_gui.exe aufgetreten, doch wurde diese im Benutzercode nicht verarbeitet.
    
    Zusätzliche Informationen: Der Einstiegspunkt "Func" wurde nicht in der DLL "bib.dll" gefunden.
    

    Wo liegt der Denkfehler? Alle Dateien liegen natürlich im gleichen Verzeichnis, die DLL wird also an sich gefunden.

    Edit:
    Das ganze auf einem Windows 7, 64-bit, mit installiertem Visual Studio 2015



  • Da fehlt extern "C" im C++ DLL Code um das Namemangeling zu deaktivieren.
    Das dürfte zumindest die EntryPointNotFoundException erklären.



  • extern "C" hatte ich vorher schon probiert, jetzt den Quelltext entsprechend abgeändert, Fehler bleibt leider gleich:

    Unbehandelte Ausnahme: System.BadImageFormatException: Es wurde versucht, eine D
    atei mit einem falschen Format zu laden. (Ausnahme von HRESULT: 0x8007000B)
       bei App.Program.Func(Int32 a)
       bei App.Program.Main(String[] args)
    


  • Wieso gleich, das ist doch jetzt ein anderer Fehler?

    Hatte das Problem auch mal, die Lösung war dass die Dll in 32 bit und das C# Programm in 64 bit kompiliert wurde ("Any CPU")) und die deswegen nicht zusammengepasst haben.



  • In der Kommandozeilenversion ist es in beiden Fällen exakt die gleiche Fehlermeldung, in Visual Studio kommt was anderes.

    Bezüglich des 32-64-Bit-Konfliktes könntest du Recht haben.
    Wie kriegt man dann raus, welches Format DLL und .Net-Exe haben? Und wie hast du das dann kompiliert, dass zwangsweise beide die gleiche Bitness haben?



  • ch++ schrieb:

    In der Kommandozeilenversion ist es in beiden Fällen exakt die gleiche Fehlermeldung, in Visual Studio kommt was anderes.

    Bezüglich des 32-64-Bit-Konfliktes könntest du Recht haben.
    Wie kriegt man dann raus, welches Format DLL und .Net-Exe haben? Und wie hast du das dann kompiliert, dass zwangsweise beide die gleiche Bitness haben?

    Naja, halt beides in 32 bit bzw. 64 bit kompilieren. Also anstatt "Any CPU" explizit x86 (für 32 bit) oder x64 (für 64 bit) auswählen und kompilieren (sowohl die DLL als auch das C# Programm).



  • DANKE!

    Habe es jetzt auch auf der Kommandozeile hinbekommen. Das extern "C" war doch nötig

    Falls es jemanden interessiert:

    Die CLR nimmt immer die zum System passende Version, das heißt, auf einem 64-Bit-System die 64-Bit-Version. Die Kommandozeile (und Visual Studio auch?) kompilieren Maschinencode aber zumindest auf Windows 7 standardmäßig nach 32 Bit. Anstatt der Standradeingabeaufforderung muss man dann im Startmenu nach der 64-Bit Native Tools Eingabeaufforderung suchen, um eine 64-Bit-DLL zu bekommen.

    Alternativ kann man mit der /platform die CLR-Exe auf 32- oder 64-Bit beschränken


Anmelden zum Antworten