C++ + [C#] C#-Bibliothek in C++ Programm verwenden

Boron

Commander
Registriert
Sep. 2001
Beiträge
2.785
Hallo an alle MS-Jünger,

ich habe eine C#-Lib. Da ich von C# so viel Ahnung habe wie eine Küchenschabe von Fußball würde ich gerne diese Lib in einem C++ Programm nutzen. Dass ich das Programm auf C# umstelle ist völlig ausgeschlossen, aus oben genanntem Grund und ich intensivst Qt nutze, was ja bekanntlich C++ ist.

Gibt es irgendeine Möglichkeit eine C# Lib in C++ zu nutzen?
Wenn es sein muss schreibe ich auch eine "Wrapper-Bibliothek", welche die C#-Lib kapselt und selbst in C++ nutzbar ist.
Irgendwie? Irgendwas? Vielleicht über C++/CLI (das hatte ich noch nie in der Hand)?
 
Das Tool tlbexp (Befehl: "tlbexp assemblyName [/out:file] [/nologo] [/silent] [/verbose]") im .Net Framework SDK erstellt dir aus einer Assembly eine TypeLib (*.tlb) die du dann unter C++ verwenden könntest.
 
Ja schön, aber was macht der willige Entwickler mit der Datei?
Weder in der MSDN direkt, oder irgendwo anders finde ich Info was man damit machen kann/soll.
Ins VS 2008 einbinden?
Woher weiß der C++ Compiler was für Typen, Klassen, Methoden es gibt (kein Header)?
Mir fallen nicht mal präzisere Fragen ein, weil ich davon noch nie gehört habe :(.
 
So Boron, nach dem ich mich mit den Untiefen von C++ rumgeschlagen habe (ist halt nicht meine Lieblingssprache) habe ich mal die Sachen für dich etwas aufbereitet:

Folgende Dinge gilt es zu beachten wenn man C# Komponenten in C++ verwenden möchte:

Die C# Seite:
1. Ein direktes Einbinden ist nicht möglich, aber über COM lassen sich die Klassen durch Interfaces verwenden
2. In C# musst du wohl oder übel für deine Klassen entsprechende Interfaces definieren und deine Klassen müssen diese auch implementieren
3. In C# Klassen muss ein Standardkonstruktor (ohne Aufrufparameter) sein
4. Die C# Klassen und Interfaces müssen das Attribut "[System.Runtime.InteropServices.ComVisible(true)]" haben
5. Kompiliere die DLL
6. Erstelle über tlbexp die notwendige TypLibrary
7. Registriere mit regasm deine DLL

Hier der Quellcode in C# für die FTP.DLL (Beispiel):

Code:
namespace ftp
{
  // Festlegung das du das Interface über COM, z.B. in C++, verwenden willst
  [System.Runtime.InteropServices.ComVisible(true)]
  public interface IFtp
  {
    // Defintion der Methoden die über COM verwendet werden sollen
    void SendFile(string sServer, string sUser, string sPassword, string sFile, string sFileContent, bool bUsePassiveMode);
  }

  // Festlegung das du die Klasse über COM, z.B. in C++, verwenden willst
  [System.Runtime.InteropServices.ComVisible(true)]
  public class FTP : IFtp
  {
    // Öffentlicher Standard-Konstruktor (ohne Parameter) wird benötigt
    public FTP()
    {
    }

    // Hier eine Methode die dann aus C++ aufgerufen werden soll 
    // (Wichtig dabei ist das sie durch das Interface (s.o.) definiert wird
    // Bei COM wird nur über das Interface die Klasse angesprochen!
    public void SendFile(string sServer, string sUser, string sPassword, string sFile, string sFileContent, bool bUsePassiveMode)
    {
      System.Net.FtpWebRequest ftp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(sServer + "/" + sFile);
      ftp.Credentials = new System.Net.NetworkCredential(sUser, sPassword);
      ftp.UseBinary = true;
      ftp.UsePassive = bUsePassiveMode;
      ftp.Method = "STOR";
      System.IO.Stream stream = ftp.GetRequestStream();
      byte[] buffer = System.Text.Encoding.ASCII.GetBytes(sFileContent);
      stream.Write(buffer, 0, buffer.Length);
      stream.Flush();
      stream.Dispose();
    }
  }
}

Soviel zu dem, jetzt die C++ Seite, schau in die Kommentare, der Code bezieht sich auf die obige FTP.DLL bzw FTP.TLB die ich in C# erstellt habe:

Code:
#include <windows.h>
#include <comutil.h> // COM verwendet BSTR strings, _com_util::ConvertStringToBSTR erledigt die Konvertierung
#pragma comment(lib, "comsuppw.lib") // sonst gibt es einen Fehler beim Kompilieren (Abhängigkeit XYZ konnte nicht gefunden werden)

#import "ftp.tlb" // Einbinden der TLB Datei, VC importiert diese und ermittelt die Interfaces und Klassen

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
  FTP::IFtpPtr ftp; // Pointer auf das COM Interface was du ansprechen möchtest
  CoInitialize(0); // Notwendig bevor überhaupt COM Objekte verwendet werden sollen
  HRESULT hr = ftp.CreateInstance("ftp.FTP", NULL, CLSCTX_ALL); // Erzeugt eine Instanz der C# Klasse
  ftp->SendFile(
    _com_util::ConvertStringToBSTR("ftp://localhost"), 
    _com_util::ConvertStringToBSTR("anonymous"), 
    _com_util::ConvertStringToBSTR("anonymous@localhost"), 
    _com_util::ConvertStringToBSTR("MeineDatei.html"), 
    _com_util::ConvertStringToBSTR("test"), 
    true); // Aufruf einer Methode der Klasse
  return 0;
}

Im C++ Code habe ich mich jetzt nicht um das "Aufräumen" gekümmert, eine Fehlerbehandlung wäre sicher auch gut...

Viel Erfolg!

PS: Hier noch ein Link, wo man das ganze auch mal nachlesen kann: http://www.csharphelp.com/archives/archive190.html
 
Zuletzt bearbeitet:
Zurück
Oben