Announcement

Collapse
No announcement yet.

Delphi4.0-Dll-Import

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Delphi4.0-Dll-Import

    Hallo Allerseits, wie muss der Quelltext aussehen damit die Delphi-Dll fehlerfrei importiert wird?<BR>
    Delphi-Dll:<BR>
    <PRE>
    library TestLib;
    uses
    SysUtils, Classes, Windows, Forms;
    {$R *.RES}

    function TestFunction(const pInput: PChar; pOutput: PChar): Integer; stdcall;
    begin
    Result:=0;
    try
    StrPCopy(pOutput, pInput + ' (ok)');
    Result:=1;
    except
    Application.MessageBox('Fehler', 'Message', 0);
    end;
    end;
    exports
    TestFunction;
    begin
    end.
    </PRE><BR>
    C#-Programm:<BR>
    <PRE>
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Runtime.InteropServices;
    namespace Test_Dll
    {
    public class Form1:System.Windows.Forms.Form
    {
    [DllImport("TestLib.dll",
    EntryPoint="TestFunction", ExactSpelling=true)]
    public static extern int TestFunction(string pInput, string pOutput);
    private System.Windows.Forms.Label lblAnzahl;
    private System.Windows.Forms.TextBox txtText;
    private System.Windows.Forms.Button btnTest;
    private System.Windows.Forms.Button btnEnde;

    private System.ComponentModel.Container components=null;
    public Form1()
    {
    InitializeComponent();
    lblAnzahl.Text="";
    txtText.Text="";
    }
    protected override void Dispose(bool disposing)
    {
    if(disposing)
    {
    if (components!=null)
    {
    components.Dispose();
    }
    }
    base.Dispose(disposing);
    }
    private void InitializeComponent()
    {
    this.lblAnzahl = new System.Windows.Forms.Label();
    this.txtText = new System.Windows.Forms.TextBox();
    this.btnTest = new System.Windows.Forms.Button();
    this.btnEnde = new System.Windows.Forms.Button();
    this.SuspendLayout();
    // lblAnzahl
    this.lblAnzahl.Location = new System.Drawing.Point(0, 0);
    this.lblAnzahl.Name = "lblAnzahl";
    this.lblAnzahl.Size = new System.Drawing.Size(100, 16);
    this.lblAnzahl.TabIndex = 0;
    this.lblAnzahl.Text = "lblAnzahl";
    // txtText
    this.txtText.AcceptsReturn = true;
    this.txtText.Location = new System.Drawing.Point(0, 24);
    this.txtText.MaxLength = 0;
    this.txtText.Multiline = true;
    this.txtText.Name = "txtText";
    this.txtText.Size = new System.Drawing.Size(568, 208);
    this.txtText.TabIndex = 1;
    this.txtText.Text = "txtText";
    // btnTest
    this.btnTest.Location = new System.Drawing.Point(408, 240);
    this.btnTest.Name = "btnTest";
    this.btnTest.TabIndex = 2;
    this.btnTest.Text = "Test";
    this.btnTest.Click += new System.EventHandler(this.btnTest_Click);
    // btnEnde
    this.btnEnde.Location = new System.Drawing.Point(488, 240);
    this.btnEnde.Name = "btnEnde";
    this.btnEnde.TabIndex = 3;
    this.btnEnde.Text = "Ende";
    this.btnEnde.Click += new System.EventHandler(this.btnEnde_Click);
    // Form1
    this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    this.ClientSize = new System.Drawing.Size(568, 269);
    this.Controls.Add(this.btnEnde);
    this.Controls.Add(this.btnTest);
    this.Controls.Add(this.txtText);
    this.Controls.Add(this.lblAnzahl);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false);
    }
    [STAThread]
    static void Main()
    {
    Application.Run(new Form1());
    }
    private void btnTest_Click(object sender, System.EventArgs e)
    {
    string inputString, outputString;
    int Anzahl;
    inputString=txtText.Text;
    outputString="";
    Anzahl=TestFunction(inputString, outputString);
    lblAnzahl.Text=Anzahl.ToString();
    txtText.Text=outputString;
    }
    private void btnEnde_Click(object sender, System.EventArgs e)
    {
    this.Dispose();
    }
    }
    }</PRE>In Vb.net funktioniert alles einwandfrei, aber nicht in c#. Was mache ich falsch? MfG Jürgen

  • #2
    Hallo,

    sobald die Delphi-DLL den PChar-Parameter als OUTPUT-Parameter nutzt, muss auf der C#-Seite ein <b>StringBuilder</b> deklariert werden, damit das automatische Marshaling der CLR an dieser Stelle greift (Strings sind generell unter .NET nur ReadOnly). Das folgende Beispiel demonstriert dies:

    a) Delphi-DLL:
    <pre>
    <b>function</b> OSDoWork(aBuffer: PChar; iValue: Integer): Integer; <b>stdcall</b>;
    <b>begin</b>
    <b>if</b> iValue = 1 <b>then</b>
    StrCat(aBuffer, <font color="#9933CC">' (von der DLL ergänzt)'</font>)
    <b>else</b>
    StrPCopy(aBuffer, <font color="#9933CC">'(von der DLL neu zugewiesen)'</font>);
    Result := iValue;
    <b>end</b>;
    </pre>

    b) C#-Programm bindet die DLL ein:
    <pre>
    <b>using</b> System.Runtime.InteropServices;
    ...

    [DllImport(<font color="#9933CC">&quot;DelphiDLL.dll&quot;</font>, EntryPoint=<font color="#9933CC">&quot;OSDoWork&quot;</font>)]
    <b>static</b> <b>extern</b> <b>int</b> OSDoWork_String(System.Text.StringBuilder aBuffer, <b>int</b> iValue);

    <b>private</b> <b>void</b> button1_Click(<b>object</b> sender, System.EventArgs e)
    {
    System.Text.StringBuilder aSB = <b>new</b> System.Text.StringBuilder(99);
    aSB.Append(<font color="#9933CC">&quot;Testdaten&quot;</font>);
    OSDoWork_String(aSB, 1);
    MessageBox.Show(aSB.ToString());
    }
    </pre&gt

    Comment


    • #3
      Vielen Dank Herr Kosch, für die schnelle Beantwortung meiner Frage!<BR>MfG<BR>Jürgen Wollenber

      Comment

      Working...
      X