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
jus

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

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

  Alt 27. Mai 2023, 23: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 (27. Mai 2023 um 23:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.932 Beiträge
 
Delphi 12 Athens
 
#2

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

  Alt 28. Mai 2023, 13:13
Besonders die Attribute wie [Marshal...] und [LPArray...] usw., wo stehen diese Sachen eigentlich in der Doku drin?
Zum Beispiel hier:
UnmanagedType Enumeration Referenz

Viel Material gibt es dazu aber wirklich nicht. Zum Beispiel musste ich auch erst herausfinden, dass man dabei ein paar Einschränkungen hat was Rückgabewerte usw. angeht.

Das größte Problem ist aber das Debugging. Visual Studio unterstützt bei solchen DLLs leider keinerlei Debugging, so dass man von Anfang an ein gutes Logging einbauen sollte.
Sebastian Jänicke
AppCentral

Geändert von jaenicke (28. Mai 2023 um 13:15 Uhr)
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
350 Beiträge
 
Delphi 2007 Professional
 
#3

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

  Alt 2. Jun 2023, 20:31
- 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.
ja, ok habe nun ausprobiert, es war tatsächlich nur das installed Häkchen, das gefehlt hat.

@jaenicke: Bei Übergabe von array of record/struct zwischen Delphiprogramm und einer Delphi DLL kann man natürlich locker ein array of record im Parameter übergeben. Zwischen Delphiprogramm und C DLL soll ja am besten nur den Zeiger auf den 1.Record vom Array geben und die Arrayanzahl. Aber wie kann man ein array of record/struct mit IInterface zwischen Delphiprogramm und C# übergeben? Wäre es dann eine InterfaceList statt einem Array?
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.932 Beiträge
 
Delphi 12 Athens
 
#4

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

  Alt 3. Jun 2023, 01:44
Du kannst natürlich das Array auch als Parameter einer Funktion des Interfaces übergeben. Ich persönlich nutze allerdings lieber eine Interface-Liste.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
350 Beiträge
 
Delphi 2007 Professional
 
#5

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

  Alt 7. Jun 2023, 20:39
@jaenicke: ich versuche einbisschen durch deinen Hinweis mit Interfaces zu experimentieren. Ich erstelle ein Interfaceobjekt in Delphi und übergebe es an die C# DLL Methode als Parameter.
Delphi-Quellcode:
type
  TMedia = record
    Name: WideString;
    ID: Integer;
  end;
  TMediaArray = array of TMedia;

  ITransportListIntf = interface
    ['{F059A4D4-1E57-4E4C-A300-5139F53E4062}']
    procedure Clear; safecall;
    procedure Add( Name: WideString; ID: Integer ); safecall;
    procedure getList( var items: TMediaArray ); safecall;
  end;

  TTransportList = class(TInterfacedObject, ITransportListIntf)
  private
    FData: TMediaArray;
  public
    procedure Clear; safecall;
    procedure Add( Name: WideString; ID: Integer ); safecall;
    procedure getList( var items: TMediaArray ); safecall;
  end;

implementation

uses Dialogs;

{ TTransportList }

procedure TTransportList.Add(Name: WideString; ID: Integer);
begin
  SetLength(FData, Length(FData) + 1);
  FData[High(FData)].Name := Name;
  FData[High(FData)].ID := ID;
end;

procedure TTransportList.Clear;
begin
  SetLength(FData,0);
end;

procedure TTransportList.getList(var items: TMediaArray);
begin
  items := FData;
end;

end.
Code:
        [Guid("F059A4D4-1E57-4E4C-A300-5139F53E4062"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface ITransportListIntf
        {
            void Clear();
            void Add([MarshalAs(UnmanagedType.BStr)] String Name, int ID);
            void getList(out RMEDIA[] items);
        }

        [DllExport]
        public static int getMediaList([In,Out, MarshalAs(UnmanagedType.Interface)] ITransportListIntf TransportList)
        {
            //...
            TransportList.Add( mediaName, mediaID );
            //....
        }
in Delphi wird es dann wie folgt gestartet:
Delphi-Quellcode:

type
  TgetMediaList = function ( MediaList: ITransportListIntf ): Integer; stdcall;

procedure TForm1.Button1Click(Sender: TObject);
var
  TransportList: ITransportListIntf;
  MediaList: TMediaArray;
begin
  TransportList := TTransportList.Create;
  getMediaList( TransportList ); // <--- hier wird die C# DLL Methode aufgerufen
  TransportList.getList( MediaList );
end;
Grundsätzlich funktioniert es auch ohne Probleme. Jetzt habe ich aber festgestellt, dass es ein Speicherleck (Fastmm zeigt es beim Beenden an) produziert. Anscheinend wird TransportList Objekt nicht freigeben. Was muss man tun, damit es freigeben wird ?

Geändert von jus ( 7. Jun 2023 um 21:01 Uhr)
  Mit Zitat antworten Zitat
jus

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

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

  Alt 8. Jun 2023, 19:57
ok, bin jetzt einen kleinen Schritt weiter. Meine Vermutung ist, dass die Referenzzählung in Verbindung mit der C# DLL bei mir Probleme macht. Darum wäre meine Quick&Dirty Lösung, dass ich direkt beim Beenden der Methode in den Referenzzähler reinpfusche:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  TransportList: ITransportListIntf;
  MediaList: TMediaArray;
  i, j: Integer;
begin
  TransportList := TTransportList.Create;
  try
    getMediaList( TransportList ); // <--- hier wird die C# DLL Methode aufgerufen
    TransportList.getList( MediaList );
  finally
    if TransportList <> nil then
    begin
      j := TransportList._AddRef;
      for i := j downto 2 do TransportList._Release; //<----- setze manuell den Referenzzähler
    end;
  end;
end;
Damit gibt es nun keine Meldung von Fastmm, dass es einen Speicherleck gibt. Meine Frage an die Experten: Ist es total verwerflich, was ich da mache? Und gibt es da einen besseren Weg?

Geändert von jus ( 8. Jun 2023 um 20:08 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.932 Beiträge
 
Delphi 12 Athens
 
#7

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

  Alt 9. Jun 2023, 01:05
Hast du denn mal _Addref und _Release selbst implementiert und einen Haltepunkt drauf gesetzt? Dann sollte doch klar werden, wo die zusätzliche Referenz herkommt.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Antwort Antwort


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 17:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz