Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C# Record/Struct rückgabe by ref/var (https://www.delphipraxis.net/185207-record-struct-rueckgabe-ref-var.html)

EWeiss 22. Mai 2015 03:06


Record/Struct rückgabe by ref/var
 
Delphi
Delphi-Quellcode:
  PBASSVIS_PARAM = ^TBASSVIS_PARAM;
  TBASSVIS_PARAM = record
    VisHandle       : HVIS;
    VisGenWinHandle : DWORD;
    Kind            : TBASSVIS_KIND_T;
  end;
C#
Code:
    [Serializable, StructLayout(LayoutKind.Sequential)]
    public sealed class BASSVIS_PARAM
    {
        public int VisHandle;
        public IntPtr VisGenWinHandle;
        public BASSVISKind Kind;
        public BASSVIS_PARAM(BASSVISKind kind)
        {
            this.Kind = kind;
            this.VisHandle = 0;
            this.VisGenWinHandle = IntPtr.Zero;
        }

        public BASSVIS_PARAM(BASSVISKind kind, int visHandle)
        {
            this.Kind = kind;
            this.VisHandle = visHandle;
            this.VisGenWinHandle = IntPtr.Zero;
        }
    }
Die procedure
Delphi

Delphi-Quellcode:
procedure BASSVIS_Free(
    var Base: TBASSVIS_PARAM
); stdcall; external dllfile;
C#
Code:
       
//BASSVIS_Free
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("bass_vis.dll", EntryPoint = "BASSVIS_Free", CharSet = CharSet.Auto)]
public static extern void BASSVIS_Free(BASSVIS_PARAM param);

Meine Frage ist wie kann ich in C# by ref die Classe zurückgeben?

In Delphi funktioniert das soweit alles.
Delphi-Quellcode:
procedure BASSVIS_Free(var Base: TBASSVIS_PARAM); stdcall;


Wurde das Plugin freigegeben dann setze ich die Handles auf 0.
Delphi-Quellcode:
Base.VisHandle := 0;
Base.VisGenWinHandle := 0;
Wie kann ich das jetzt in C# umsetzen?
Ein einfaches
Code:
public static extern void BASSVIS_Free(ref BASSVIS_PARAM param);
Sollte eigentlich funktionieren aber bei der Umsetzung in der Anwendung gibt es Probleme.
Das würde theoretisch funktionieren.. (Zumindest wird kein Fehler angezeigt)
Code:
BassVis.BASSVIS_Free(ref_visParam);
bool bFree = _visParam.VisHandle == 0;
if (!bFree)
Das hingegen nicht..
Code:
private IVisualization Viz = null;
//...............
BassVis.BASSVIS_Free(ref Viz.VizParam);
bool bFree = Viz.VizParam.VisHandle == 0;
if (bFree)
Error:
Zitat:

Error 15 A property, indexer or dynamic member access may not be passed as an out or ref Parameter
IVisualization ist so ausgelegt..
Code:
public interface IVisualization
{
  BassVis_Api.BASSVIS_PARAM VizParam { get; }
Nur hier kann ich kein "ref" übergeben.

gruss

EWeiss 22. Mai 2015 05:29

AW: Record/Struct rückgabe by ref/var
 
Seltsam ist nur das es auch ohne "ref" in normalen Anwendungen funktioniert. C# und VB_NET
Was bedeutet das die Handles auf 0 gesetzt sind wenn ich ein Plugin beende.

Nur mit dem Mediaportal will das nicht obwohl es die gleichen Dateien (DLL's) sind.
Sehr komisch das ganze.

gruss

Dejan Vu 22. Mai 2015 06:46

AW: Record/Struct rückgabe by ref/var
 
Eine Property hat keine Adresse, deshalb wird das nicht gehen. Abhilfe:
a) Statt oder zusätzlich zur Property die Variable/Feld publizieren (Nicht so schön)
b) Eine explizite Methode schreiben, die den Wert aus der DLL liest. Diese Methode hat dann Zugriff auf den privaten Backing Store der Property

Code:
Interface IBassVizDLLAccess
{
  void BASSVIS_Free(ref parm);
}

class Foo : IVisualization
{
  private BASSVIS_PARAM vizParam;
 
  public BASSVIS_PARAM VizParam {get {return vizParam;} }

  public void ReadViz (IBassVizDLLAccess BassViz)
  {
     BassVis.BASSVIS_Free(ref_vizParam);
  }
}
Und deine DLL-Zugriffsklasse implementiert dann IBassVizDLLAccess.

EWeiss 22. Mai 2015 16:40

AW: Record/Struct rückgabe by ref/var
 
Du meins das würde reichen?

Code:
public BASSVIS_PARAM VizParam {get {return vizParam;} }
Seltsam bleibt jedoch warum in meinen samples für .NET alles auch ohne "ref" funktioniert.
Nur in Mepo halt nicht.
Die WrapperDLL und die BassVisDLL sind gleich.
Nicht das ich das Programm verwende aber es ärgert mich halt wenn etwas nicht so läuft wie man es eigentlich erwartet.

Funktioniert leider nicht.
Aber kein Problem ich vergesse MediaPortal ganz einfach.
In meinen Samples funktioniert es ja.

gruss

himitsu 22. Mai 2015 18:57

AW: Record/Struct rückgabe by ref/var
 
Zitat:

Zitat von EWeiss (Beitrag 1302618)
Seltsam bleibt jedoch warum in meinen samles für .NET alles auch ohne "ref" funktioniert.

Vielleicht weil dort praktisch fast Alles auf Referenzen (Objekten) bassiert?

EWeiss 22. Mai 2015 19:19

AW: Record/Struct rückgabe by ref/var
 
Zitat:

Zitat von himitsu (Beitrag 1302637)
Zitat:

Zitat von EWeiss (Beitrag 1302618)
Seltsam bleibt jedoch warum in meinen samles für .NET alles auch ohne "ref" funktioniert.

Vielleicht weil dort praktisch fast Alles auf Referenzen (Objekten) bassiert?

Kannst du das näher erklären
So das ich es verstehe.. was damit gemeint ist.

gruss

himitsu 22. Mai 2015 19:33

AW: Record/Struct rückgabe by ref/var
 
C# und andere Spachen kapseln sogar einfache Typen, wie z.B. einen Integer, in je einem Objekt (bzw. sie können eventuell auch beide Modi)
Das ist z.B. ein Grund, warum JavaScript oder PHP in einer Variable "alles" halten können, ohne Diese typisieren zu müssen. (auch wenn man das intern "inzwischen" teilweise wieder "optimiert" und doch wieder versucht es nativ zu speichern, wenn es geht)

Ein Delphi-Objekt wird ja auch immer per Referenz übergeben, selbst wenn man die Variable nicht als Referenz (VAR) übergibt.

EWeiss 22. Mai 2015 19:45

AW: Record/Struct rückgabe by ref/var
 
Erklärt aber noch nicht den Unterschied zwischen MePo C# und meinem Sample C# sowie dem in VB_NET
Warum meine Anwendungen Funktionieren aber die andere nicht.

Ich kann mich ja nicht nach einer speziellen Anwendung richten sondern diese muss sich nach den Begebenheiten richten
die meine Dll exportiert.

Welche das sind habe ich ja aufgezeigt.
Würde es also überall fehlschlagen hätte ich ein Design Problem aber dem ist ja nicht so.

gruss

himitsu 22. Mai 2015 20:02

AW: Record/Struct rückgabe by ref/var
 
Selber verstehen und vorallem machen kann ich es nicht ... bin froh, wenn ich's halbwegs lesen/entziffern kann.

Aber vielleicht erklärt das es ja ein bissl.
https://msdn.microsoft.com/de-de/library/yz2be5wk.aspx
http://www.dotnet-tricks.com/Tutoria...-Unboxing-in-C

https://msdn.microsoft.com/de-de/library/dd264741.aspx
http://www.tutorialspoint.com/csharp...data_types.htm
http://stackoverflow.com/questions/2...ence-type-in-c

EWeiss 22. Mai 2015 20:10

AW: Record/Struct rückgabe by ref/var
 
Zitat:

Zitat von himitsu (Beitrag 1302665)

Danke :)
Habe mich im World Wide Web schon umgesehen.

Ich lasse es jetzt so wie es ist also ohne Rückgabe bei ref.
Maßgeblich sind meine Samples da funktioniert es ja so wie es soll.
Andere Anwendungen müssen sich halt die passende Lösung selber suchen.

Das ist was ich zurückgebe und das ist korrekt.
Delphi-Quellcode:
procedure BASSVIS_Free(var Base: TBASSVIS_PARAM); stdcall;
//......    
BASSVISKIND_WMP:
begin
  BASSWMPVisAPI.WMPVIS_Free(Base.VisHandle);
  if BASSWMPVisAPI.WMPVIS_IsFree then
  begin
    Base.VisHandle := 0;
    Base.VisGenWinHandle := 0;
  end;
end;
gruss

Dejan Vu 23. Mai 2015 07:39

AW: Record/Struct rückgabe by ref/var
 
Bei Delphi ist das ein Rekord. Mit 'var' wird auf den Parameter per übergebener Referenz zugegriffen und Du kannst den Inhalt bearbeiten.

Bei C# wird die Referenz übergeben, weswegen das imho überhaupt erst funktioniert. Die Referenz an sich wird nicht verändert.

Wäre TBASSVIZ_PARAM eine Klasse, bräuchtest Du in Delphi das 'var' nicht, aber dann könntest Du von C# nicht drauf zugreifen.

EWeiss 23. Mai 2015 08:31

AW: Record/Struct rückgabe by ref/var
 
Zitat:

Bei Delphi ist das ein Rekord. Mit 'var' wird auf den Parameter per übergebener Referenz zugegriffen und Du kannst den Inhalt bearbeiten.
Ja das ist mir schon klar ;)

Zitat:

Bei C# wird die Referenz übergeben, weswegen das imho überhaupt erst funktioniert. Die Referenz an sich wird nicht verändert.
An dieser aussage kann irgend etwas nicht stimmen..
Oder aber ich bin schlichtweg zu blöd dafür.

2 Kriterien die dagegen sprechen.

In meinen beiden Samples C# und VB_NET. Funktioniert es ohne übergabe aus meiner WrapperDLL.
Also.
WrapperDLL.
Code:
//BASSVIS_Free
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("bass_vis.dll", EntryPoint = "BASSVIS_Free", CharSet = CharSet.Auto)]
public static extern void BASSVIS_Free(BASSVIS_PARAM param);
Funktioniert also..
Aber nicht mit MediaPortal.

übergebe ich aus dem Wrapper bei "ref"
Code:
//BASSVIS_Free
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("bass_vis.dll", EntryPoint = "BASSVIS_Free", CharSet = CharSet.Auto)]
public static extern void BASSVIS_Free(ref BASSVIS_PARAM param);
funktionieren meine Samples nicht mehr.
MediaPortal sowieso nicht.
Weil ich Probleme habe dein Beispiel umzusetzen.
Es gibt da mehr als ein Interface in der ich das kapseln muss.

Warum also funktionieren meine Samples ohne Übergabe bei "ref" und mit dann nicht mehr ?
Natürlich habe ich dann die Funktionen in den Samples Angepasst.
Code:
BassVis.BASSVIS_Free(ref mVisParam);
bFree = mVisParam.VisHandle == 0;
bFree ist dann immer False weil das Handle > 0 (mit "ref") ohne ist es 0.

Kann es sein das es nicht ausreicht nur param by ref zurückzugeben?
Müsste ich speziell für den Fall noch selbst für die Rückgabe der Handles aus dem Wrapper sorgen?
Obwohl das eigentlich mir "ref" erledigt sein sollte.

Deshalb mein Einwand!

gruss

EWeiss 23. Mai 2015 08:54

AW: Record/Struct rückgabe by ref/var
 
Vorher hatte ich eine Function zum prüfen ob das Handle 0 ist.
Delphi-Quellcode:
function BASSVIS_IsFree(Param: PBASSVIS_PARAM): BOOL; stdcall;


Diese wollte ich mir durch das bei "var" sparen.
Weil jegliche zusätzliche Export Funktion das Arbeiten mit der DLL unnötig verkompliziert.
Aber scheinbar geht es nicht ohne.

gruss

Dejan Vu 23. Mai 2015 11:11

AW: Record/Struct rückgabe by ref/var
 
Ich bin auch etwas verwirrt. Vielleicht habe ich auch etwas falsch verstanden. Könntest Du noch einmal genau wiedergeben, wie die Methode in der DLL deklariert ist, oder den Post zeigen, wo das erklärt ist.

EWeiss 23. Mai 2015 11:28

AW: Record/Struct rückgabe by ref/var
 
Zitat:

Zitat von Dejan Vu (Beitrag 1302733)
Ich bin auch etwas verwirrt. Vielleicht habe ich auch etwas falsch verstanden. Könntest Du noch einmal genau wiedergeben, wie die Methode in der DLL deklariert ist, oder den Post zeigen, wo das erklärt ist.

Gerne doch wenn es hilft.

Der Wrapper Schnittstelle zwischen BassVis.dll und der .NET Anwendung.
Damit User die VB_NET verwenden nicht so viel Probleme mit unmanaged code haben.
Zudem können beide .NET Environment dann diese eine DLL als reference zum Projekt hinzufügen.

Die Class BASSVIS_PARAM..
Code:
    [Serializable, StructLayout(LayoutKind.Sequential)]
    public sealed class BASSVIS_PARAM
    {
        public int VisHandle;
        public IntPtr VisGenWinHandle;
        public BASSVISKind Kind;
        public BASSVIS_PARAM(BASSVISKind kind)
        {
            this.Kind = kind;
            this.VisHandle = 0;
            this.VisGenWinHandle = IntPtr.Zero;
        }

        public BASSVIS_PARAM(BASSVISKind kind, int visHandle)
        {
            this.Kind = kind;
            this.VisHandle = visHandle;
            this.VisGenWinHandle = IntPtr.Zero;
        }
    }
und die external Funktion vom Export aus der BassVis.dll
Code:
//BASSVIS_Free
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("bass_vis.dll", EntryPoint = "BASSVIS_Free", CharSet = CharSet.Auto)]
public static extern void BASSVIS_Free(ref BASSVIS_PARAM param);
Der Record in BassVis.dll (Delphi Seite)
Delphi-Quellcode:
  PBASSVIS_PARAM = ^TBASSVIS_PARAM;
  TBASSVIS_PARAM = record
    VisHandle       : HVIS;           // VisHandle
    VisGenWinHandle : DWORD;          // General Vis Window Handle W5
    Kind            : TBASSVIS_KIND_T; // Aktive Plugin Art
  end;
die Funktion die exportiert wird.
Delphi-Quellcode:
procedure BASSVIS_Free(var Base: TBASSVIS_PARAM); stdcall;


gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:17 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