AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Wie ein array of record von C# dll mit COM an Delphi übergeben?
Thema durchsuchen
Ansicht
Themen-Optionen

Wie ein array of record von C# dll mit COM an Delphi übergeben?

Ein Thema von jus · begonnen am 26. Mai 2023 · letzter Beitrag vom 9. Jul 2023
Antwort Antwort
Seite 1 von 3  1 23      
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#1

Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 02:16
Hallo,

ich bin am verzeifeln. Ich möchte in Delphi eine Methode von einer C# DLL aufrufen und einen array of record in Delphi bekommen. Das Record könnte so aussehen:
Delphi-Quellcode:
RMEDIA = packed record
  Name: String;
  ID: Integer;
end;
Dazu Ich habe einfach in Visual Studio 2019 eine "Class Library (.NET Framework)" Project erstellt und eine DLL mit einer einzigen Methode erstellt. Diese DLL lade ich einfach in Komponenten importieren->Typenbibliothek rein und erhalte eine TLB Unit in Delphi. Wenn die Funktionsparameter nur aus String oder Integer bestehen funktioniert es auch wunderbar. Doch wie kann ich von C# aus array of struct/record als Parameter übergeben?
Auf C# Seite habe ich mal folgendes versucht:
Code:
using System;
using System.Collections.Generic;

using System.ComponentModel;
using System.Data;
using System.Drawing;

using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Runtime.InteropServices;


namespace DelphiTest
{
    public class CrossDLL
    {
        public struct RMEDIA
        {
            public String Name;
            public int ID;
        }

        public string HelloWorldArray(out RMEDIA[] structArray, ref int arraySize)
        {
            arraySize = 2;

            // Create an array of MyStruct
            structArray = new RMEDIA[arraySize];

            // Populate the array with data
            for (int i = 0; i < arraySize; i++)
            {
                structArray[i].ID = i + 1;
                structArray[i].Name = "Hallo";
            }
            return $"";
        }
    }
}
Wenn ich diese erstellte DLL in Delphi über die Komponente installieren->Typenbibliothek importierenreinlade erhalte folgende Methode:
function HelloWorldArray(out structArray: PSafeArray; var arraySize: Integer): WideString; Wenn ich folgendes versuche:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  CrossDLL: TCrossDLL;
  Items: PSafeArray;
  arraySize: Integer;
begin
  CrossDLL :=TCrossDLL.Create(self);
  CrossDLL.HelloWorldArray(Items, arraySize);
end;
bekomme ich gleich folgende eine Fehlermeldung:
Code:
---------------------------
Project1
---------------------------
Altes Format oder ungültige Typbibliothek. (Ausnahme von HRESULT: 0x80028019 (TYPE_E_UNSUPFORMAT))
---------------------------
OK  
---------------------------
Hat jemand einen Ansatz für mich?
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 08:19
Mir geht es im Moment nicht gut, deshalb nur kurz:
Ich verwende das NuGet Paket DllExport und erstelle damit nativ exportierte Funktionen. Die DLL kann man dann in Delphi einfach mit LoadLibrary laden.

Ich habe darum herum dann ein Framework gebaut, mit dem ich C#-Interfaces generisch aus Delphi heraus abrufen oder umgekehrt in der C#-DLL Interfaces aus der Delphi-Hostanwendung abrufen kann. Auf diese Weise kann ich auch z.B. direkt generische Listen in beiden Richtungen als Parameter verwenden. Aber für dich reichen ja die nativen Funktionen vermutlich schon.

Nächste Woche kann ich dazu bei Bedarf auch mehr schreiben. Den entsprechenden Quelltext kann ich aber leider nicht zeigen.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 11:11
Was willst du im C# mit diesem Record machen?

Wenn nur lesen, dann kann String als PChar angesehen werden (also char* und vielleicht auch char[] bis 2007 und wchar ab Delphi 2009)

Überschreiben einzelner Chars ginge zwar auch, aber nur sicher, wenn vorher Delphi-Referenz durchsuchenUniqueString,
und die länge Ändern bedingt einen Zugriff auf den Delphi-Speichermanager, also grundsätzlich somit erstmal NEIN, für Schreibzugriffe.




Warum benutzt du denn keinen WideString?
Das ist eine Kapselung des BSTR vom C++, also von MSDN-Library durchsuchenSysAllocString und seinen Freunden, welches auch C# verstehen sollte.
$2B or not $2B

Geändert von himitsu (26. Mai 2023 um 11:19 Uhr)
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#4

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 11:25
@himitsu: zunächst möchte die Record Arrays in Delphi nur mal einlesen können. Wie schon gesagt funktioniert die Sache mit einfachen Typen wie String und Integer ohne Probleme. Ich weiß halt nur nicht wie ich ein Array of Record von C# an Delphi weitergebe, so dass der Delphi Typenbibliothek Import einwandfrei klappt.
Der Hintergrund ist, dass es vom Hersteller nur eine C# DLL existiert. Und auch die ganze Doku für C# ausgelegt ist. Da ich es aber in Delphi vewenden möchte, habe ich mir gedacht, dass ich dafür eine C# COM Wrapper DLL schreibe, die ich einfach über die Delphi Typenbibliothek importiere.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 12:08
Ach andersrum

in Delphi gefüllt -> in C# lesen
in C# gefüllt -> in Delphi lesen



Jetzt müsste man wissen, wie im C# deren "String" intern aufgebaut ist.
Ich würde mal vermuten es ist ein PPChar ... ein PChar-kompatibler Typ, der in einem Objekt verpackt wurde.

Hilft aber nur, wenn du manuell die Konvertierung/Übergabe machst.



Vermutete einfachste Lösung: benutze das, was im C# einem BSTR (aka WideString) entspricht.
Oder eben einen OleVariant.



Man kann sich auf das Minimum konzentrieren und muß auf der anderen Seite etwas Gleichwertiges, oder zumindest Kompatibles finden.

PChar ist ein Zeiger auf Chars, die durch #0 terminiert (abgeschlossen) werden.

Die "LongStrings" von Delphi (String, AnsiString, UnicocdeString) sind intern kompatibel mit einem PChar.
-> die Verwaltungsdaten liegen rückwertig vor dem internen Zeiger (der auf das erste Char zeigt) und hinter dem letzten Char befinden sich implizit zwei #0.
Drum lässt sich ein String problemlos in einen PChar casten.

Der ShortString (hieß gaaaaanz früher mal "string") ist ein Record, bzw. statisches CharArray, wo der Char[0] das Längenbyte darstellt. (drum fangen im Delphi auch alle Strings auch mit 1 an )

Der "OLE-String" WideString basiert intern auf einem BSTR und benutzt die APIs SysAllocString/SysReAllocString/SysFreeString der oleauto.h bzw. OleAut32.dll.
$2B or not $2B

Geändert von himitsu (26. Mai 2023 um 12:12 Uhr)
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#6

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 16:35
@jaenicke: vielen Dank für den Hinweis mit dem DllExport. Wie so oft hast du mir ja schon weitergeholfen! Ich habe zwar nicht DllExport Package verwendet, sondern das Unmanaged Exports Nuget Package von Stackoverflow Beispiel verwendet. Ich habe das Unmanaged Exports Package von Robert Giesecke in mein Visual Studio 2019 Community Projekt installiert. Es gab zwar am Anfang paar Fallstricken bis es lief, aber dann habe ich einfach das Stackoverflow Beispiel hergenommen und das Record um weitere einfache Typen erweitert. Die Erweiterung funktionierte auf Anhieb. Falls es jemand interessiert, kann ich ja mal nachreichen.
Was dein Angebot bzgl. deinen Ansatz mit DllExport betrifft, so wäre ich sehr interessiert. Natürlich erst, wenn es dir wieder besser geht. Vielleicht könntest du ein kurzes Beispiel für DllExport zeigen. Wünsche gute Besserung!!!

lg,
jus
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 19:17
Ich habe zwar nicht DllExport Package verwendet, sondern das Unmanaged Exports Nuget Package von Stackoverflow Beispiel verwendet.
Das ist im Grunde das gleiche, auch von der Verwendung her. DllExport ist neuer, das Unmanaged Exports wird schon länger nicht mehr gepflegt, weshalb ich für neue Projekte das neuere empfehlen würde. Außerdem ist das durch den Wizard für die Projektkonfiguration sogar noch einfacher.

Was dein Angebot bzgl. deinen Ansatz mit DllExport betrifft, so wäre ich sehr interessiert.
Die Grundidee ist, dass man auf beiden Seiten je eine Klasse bereitstellt, die über eine exportierte Funktion verbunden werden. Dann fragt man an dieser Klasse ein Interface an, diese extrahiert die GUID und fragt die jeweils andere Seite danach. Die liefert dann ein passendes IInterface zurück, das man dann mit Supports in den konkreten Typ casten kann.

Darüber kann man dann noch einen generischen Aufsatz schreiben, damit es einfach zu verwenden ist.

Diesen Ansatz habe ich nun schon dreimal entworfen und er wurde jedesmal besser. Zuerst habe ich damit privat gespielt, aber das war nur ein Grundgerüst, dann habe ich es zweimal richtig für berufliche Zwecke implementiert, am Ende dann auch mit C#.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#8

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 22:43
...Das ist im Grunde das gleiche, auch von der Verwendung her. DllExport ist neuer, das Unmanaged Exports wird schon länger nicht mehr gepflegt, weshalb ich für neue Projekte das neuere empfehlen würde. Außerdem ist das durch den Wizard für die Projektkonfiguration sogar noch einfacher.
Hmm.. ich habe mir das Nuget Package "DllExport" über "Manage Nuget Packages..." von Visual Studio 2019 Community Edition in ein quasi leeres Projekt hinzugefügt.
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace DelphiCrossV2
{
    public class Test
    {
        [DllExport]
        public static int TestExport(int left, int right)
        {
            return left + right;
        }
    }
}
Es funktioniert bei mir irgendwie nicht. Irgendwas mache ich da falsch. Sobald ich den Befehl [DllExport] kommt da folgende Fehlermeldungen:
Code:
error CS0246: The type or namespace name 'DllExport' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'DllExport' could not be found (are you missing a using directive or an assembly reference?)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 26. Mai 2023, 23:56
- Klassenbibliothek (.NET Framework) erstellen
- In den Projekteigenschaften unter Build --> Allgemein das Plattformziel auf x86 setzen
- Bezeichnungen der Klassen / Namespace usw. setzen
- DllExport installieren
--> Es öffnet sich dieses Fenster:
2023-05-26.png
Dort das Häkchen bei "Installed" setzen wie im Screenshot zu sehen und Apply drücken! Der Namespace sollte automatisch passen, wenn es ein neues Projekt ist, aber den kann man dort ggf. auch anpassen.

Dann auf Aufforderung des Visual Studios die Mappe neu laden (weil die Projektdatei extern geändert wurde).

Nun sollte DllExport gefunden werden.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#10

AW: Wie ein array of record von C# dll mit COM an Delphi übergeben?

  Alt 28. Mai 2023, 00:27
- Klassenbibliothek (.NET Framework) erstellen
- In den Projekteigenschaften unter Build --> Allgemein das Plattformziel auf x86 setzen
- Bezeichnungen der Klassen / Namespace usw. setzen
- DllExport installieren
--> Es öffnet sich dieses Fenster:
Anhang 56072
Dort das Häkchen bei "Installed" setzen wie im Screenshot zu sehen und Apply drücken! Der Namespace sollte automatisch passen, wenn es ein neues Projekt ist, aber den kann man dort ggf. auch anpassen.

Dann auf Aufforderung des Visual Studios die Mappe neu laden (weil die Projektdatei extern geändert wurde).

Nun sollte DllExport gefunden werden.
ah ok, danke für die tolle Hilfestellung! Das mit dem installed Häkchen setzen habe ich nicht gewußt , ich dachte mit der Standardeinstellung funktioniert es schon. Da mein USG Router daheim abgeraucht ist, werde ich nächste Woche in der Firma es ausprobieren. Weiters muss ich zugeben, dass ich mich in VisualStudio C# überhaupt nicht firm bin. Gibt es irgendwelche guten Dokus oder Beispiele zum DllExport? Ich habe mir das Youtube Video und die paar wenige Beispiele von DllExport auf deren Github Hauptseite angeschaut, werde aber irgendwie nicht ganz schlau damit. Besonders die Attribute wie [Marshal...] und [LPArray...] usw., wo stehen diese Sachen eigentlich in der Doku drin?

Geändert von jus (28. Mai 2023 um 00:35 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz