Hallo,<BR>ist es möglich in Delphi4.0 geschriebene Klassen in C# zu nutzen (über Dll)?<BR>MfG<BR>Jürgen
Announcement
Collapse
No announcement yet.
Delphi4.0-Klassen in C# nutzen
Collapse
X
-
Als Klasse nicht.
Aber wenn Du dir ein Funktionsinterface dafür erstellst und diese DLL-Funktionen entsprechend C#-Syntax einbindest schon.
Für jede Methode die du von der Klasse verwenden willst lege ein DLL-Funktion an. Wenn du die Klasse in mehreren Instanzen verwenden willst mußt Du als ersten Parameter noch einen Handle-parameter definieren der die Instanz der Klasse bestimmt.
Die 2te Möglichkeit wäre über COM zu gehen. Erstellen eine COM-Wrapper und binde diesen dann in C# ein.
Ich würde die erste Methode bevorzugen, da dur die COM-Probleme (Registrierung, Versionsproblem) sparst
-
Hallo Bernhard,<BR>danke für deine schnelle Antwort, hättest Du vielleicht ein kleines Code-Beispiel auf Lager?<BR>Die erste Idee scheint mir auch die Bbessere zu sein. Ich würde das ganze Spektum einer Klasse nutzen wollen (Eigenschaften, Methoden und ganz wichtig Ereignisse).<BR>Wäre nett, wenn du mir auch dort helfen könntest.<BR>Danke in Voraus!<BR>MfG<BR>Jürge
Comment
-
Hallo,
wenn die "alte" DLL-Schnittstelle über <i>P/Invoke</i> bedient werden soll, muss die eigene Delphi-DLL für jede Funktion eine so genannten Schnittstellenprozedur (siehe Delphi-Hilfe) deklarieren und exportieren. Allerdings kann auf diesem Weg keine Klasseninstanz übertragen werden.
Der einzige "saubere" Weg besteht darin, die Delphi-Klasse über ein Automation-Objekt (COM) zu verpacken, und von .NET aus diese Umverpackung über <i>COM Interop</i> zu nutzen. Nur so lassen sich auch Ereignisse (Events) in Richtung .NET transportieren. Eine Schnittstellen-Prozedur (reine DLL-Schnittstelle ohne COM) kann so etwas nicht leisten.
In einem praktischen Beispiel sieht das dann so aus (ein C#-Client greift auf ein Delphi 6-Automationobjekt zu, das Events auslöst). Die eigene Hilfsklasse <i>AdressverwaltungEventsHelperClass</i> implementiert das Interface IAutObjEvents des Automation-Objekts, um dort gleich 2 Aufgaben zu erfüllen: <br>
1. Nutzfunktion der Events von IAutObjEvents <br>
2. Kontrollieren der Lebensdauer der Interface-Zeiger
<pre>
<b>using</b> System;
<b>using</b> System.Runtime.InteropServices;
<b>using</b> System.Windows.Forms;
<b>namespace</b> AdressverwaltungCSClient
{
<font color="#003399"><i>/// <summary></i></font>
<font color="#003399"><i>/// Hilfsklasse kapselt die Events der Adressverwaltung ein</i></font>
<font color="#003399"><i>/// </summary></i></font>
<b>public</b> <b>class</b> AdressverwaltungEventsHelperClass: Adressverwaltung.IAutObjEvents
{
<b>private</b> Form1 aMainForm;
<b>private</b> UCOMIConnectionPoint icp;
<b>private</b> UCOMIConnectionPointContainer icpc;
<b>private</b> <b>int</b> cookie;
<font color="#003399"><i>/// <summary></i></font>
<font color="#003399"><i>/// Default-Konstruktor (ohne eigene Funktion)</i></font>
<font color="#003399"><i>/// </summary></i></font>
<b>public</b> AdressverwaltungEventsHelperClass()
{
}
<font color="#003399"><i>/// <summary></i></font>
<font color="#003399"><i>/// Überladener Konstruktor legt Verweis auf das Hauptformular in einem</i></font>
<font color="#003399"><i>/// eigenen Objektfeld (aMainForm) ab und baut dann die Verbindung zur</i></font>
<font color="#003399"><i>/// ConnectionPoint-Schnittstelle von COM auf.</i></font>
<font color="#003399"><i>/// </summary></i></font>
<font color="#003399"><i>/// <param name="aForm"></param></i></font>
<b>public</b> AdressverwaltungEventsHelperClass(Form1 aForm)
{
aMainForm = aForm;
icpc = (UCOMIConnectionPointContainer)aMainForm.aObj;
Guid IID_IMyEvents = <b>typeof</b>(Adressverwaltung.IAutObjEvents).GUID;
icpc.FindConnectionPoint(<b>ref</b> IID_IMyEvents,<b>out</b> icp);
icp.Advise(<b>this</b>,<b>out</b> cookie);
}
<font color="#003399"><i>/// <summary></i></font>
<font color="#003399"><i>/// Der Anwender hat in der Adressverwaltung auf den Button »Weiter« geklickt,</i></font>
<font color="#003399"><i>/// die Kundendaten liegen somit vor, die Verbindung zur Adressverwaltung </i></font>
<font color="#003399"><i>/// kann abgebaut werden. Dazu ruft das Programm die Interface-Methode »pQuit«</i></font>
<font color="#003399"><i>/// des Automations-Objekts (nicht des Events-Objekts!) auf.</i></font>
<font color="#003399"><i>/// </summary></i></font>
<font color="#003399"><i>/// <param name="vAdrId"> <description>Adress-ID des Kunden </description></param></i></font>
<font color="#003399"><i>/// <param name="vAdrAend"></param></i></font>
<font color="#003399"><i>/// <param name="vVersNr"></param></i></font>
<b>public</b> <b>void</b> OnNext(<b>object</b> vAdrId, <b>object</b> vAdrAend, <b>object</b> vVersNr)
{
aMainForm.DoSetData(vAdrId.ToString(), vAdrAend.ToString());
aMainForm.aObj.pQuit();
}
<font color="#003399"><i>/// <summary></i></font>
<font color="#003399"><i>/// Benutzer hat den Abbrechen-Button in der Adressverwaltung angeklickt, damit </i></font>
<font color="#003399"><i>/// das Programmfenster der Adressverwaltung ohne Warnhinweis verschwindet, muss</i></font>
<font color="#003399"><i>/// der "offizielle" Weg des Verbindungsabbaus beschritten werden. Das eigene</i></font>
<font color="#003399"><i>/// Programm ruft dazu die Interface-Methode »pQuit« des Automations-Objekts auf. </i></font>
<font color="#003399"><i>/// </summary></i></font>
<b>public</b> <b>void</b> OnAbort()
{
aMainForm.aObj.pQuit();
}
<font color="#003399"><i>/// <summary></i></font>
<font color="#003399"><i>/// Das Event-Objekt der Adressverwaltung kündigt das Programmende an, das eigene</i></font>
<font color="#003399"><i>/// Programm muss alle aktiven Interface-Zeiger freigeben, damit Windows für die</i></font>
<font color="#003399"><i>/// Adressverwaltung nicht den Warnhinweis für die noch offenen COM-Verbindungen</i></font>
<font color="#003399"><i>/// anzeigt. </i></font>
<font color="#003399"><i>/// </summary></i></font>
<b>public</b> <b>void</b> OnQuit()
{
icp.Unadvise(cookie);
<font color="#003399"><i>// 1. Interface </i></font>
<b>while</b> (Marshal.ReleaseComObject(icp) > 0)
;
icp = <b>null</b>;
<font color="#003399"><i>// 2. Interface</i></font>
<b>while</b> (Marshal.ReleaseComObject(icpc) > 0)
;
icpc = <b>null</b>;
}
}
}
</pre>
Aufruf im C#-Programm:
<pre>
<b>public</b> Adressverwaltung.AutObjClass aObj;
<b>public</b> <b>void</b> DoSetData(<b>string</b> sAdr_id, <b>string</b> sDatum)
{
label1.Text = sDatum;
label2.Text = sAdr_id;
}
<b>private</b> <b>void</b> buttonStartSinkContainer_Click(<b>object</b> sender, System.EventArgs e)
{
aObj = <b>new</b> Adressverwaltung.AutObjClass();
AdressverwaltungEventsHelperClass aSinkHelper = <b>new</b> AdressverwaltungEventsHelperClass(<b>this</b>);
aObj.fStart(0,<b>null</b>);
}
</pre>
Comment
Comment