Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C# Zugriff auf Struct (https://www.delphipraxis.net/184644-zugriff-auf-struct.html)

EWeiss 11. Apr 2015 21:08

Zugriff auf Struct
 
Hoffe jemand kann helfen. ;)

Code:
  [Serializable, StructLayout(LayoutKind.Sequential)]
  public sealed class TAudioAttributes
  {
    public int Channels;
    public int SamplesPerSec;
    public int BitsPerSample;
    public double PlayTime;
    public UInt64  SampleCount;
    public int Bitrate;
  }
Code:
    //TagsLibrary_GetAudioAttributes
    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("TagsLib.dll", EntryPoint = "TagsLibrary_GetAudioAttributes", CharSet = CharSet.Auto)]
    public static extern bool TagsLibrary_GetAudioAttributes(IntPtr HTags, TAudioType AudioType, IntPtr Attributes);
Aufruf in VB_NET

Code:
        Dim AudioAttributes As IntPtr

        If TagsLib.TagsLibrary_GetAudioAttributes(hTags, TAudioType.atAutomatic, AudioAttributes) Then
            txtChannels.Text = AudioAttributes.Channels.ToString
            txtSamplesPerSec.Text = AudioAttributes.SamplesPerSec.ToString
            txtBitsPerSample.Text = AudioAttributes.BitsPerSample.ToString
            txtPlayTime.Text = AudioAttributes.PlayTime.ToString
            txtSampleCount.Text = AudioAttributes.SampleCount.ToString
            txtBitRate.Text = AudioAttributes.Bitrate.ToString
        End If
AudioAttributes soll mir also einen pointer auf die TAudioAttributes struct zurück liefern.
Wie muss also die Rückgabe für die Struct geschrieben werden damit in VB_NET
ein zugriff auf

Code:
AudioAttributes.SamplesPerSec.ToString
erfolgen kann.

Für PWideChar musste ich auch so tricksen. (Was funktioniert)
Code:
    //TagsLibrary_GetTag
    public static string TagsLibrary_GetTag(IntPtr HTags, string Name, TTagType TagType)
    {
      IntPtr ptr = TagsLibrary_GetTagPtr(HTags, Name, TagType);
      if (ptr != IntPtr.Zero)
      {
        return Marshal.PtrToStringAuto(ptr);
      }
      return null;
    }
    [DllImport("TagsLib.dll", EntryPoint = "TagsLibrary_GetTag", CharSet = CharSet.Auto)]
    private static extern IntPtr TagsLibrary_GetTagPtr(IntPtr HTags, [In, MarshalAs(UnmanagedType.LPWStr)] string Name, TTagType TagType);



gruss

jfheins 11. Apr 2015 21:40

AW: Zugriff auf Struct
 
Zunächst mal solltest du für unmanaged interop besser struct verwenden als Klassen.
(Zumindest habe ich struct verwendet, als ich sowas gemacht habe, ich bin mir daher sicher, dass es geht)

Was die folgende Konvertierung angeht, habe ich die Methoden hier benutzt:
Code:
 internal static byte[] struct2bytes<T>(T packet)
            where T:struct
        {
            int size = Marshal.SizeOf(packet);
            byte[] arr = new byte[size];
            IntPtr ptr = Marshal.AllocHGlobal(size);

            Marshal.StructureToPtr(packet, ptr, false);
            Marshal.Copy(ptr, arr, 0, size);
            Marshal.FreeHGlobal(ptr);

            return arr;
        }

        internal static T bytes2struct<T>(byte[] bytes)
            where T:struct
        {
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            var s = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
            handle.Free();

            return s;
        }
Insbesondere die Methode Marshal.PtrToStructure sollte zu deinem Anwendungsfall passen ;-)
(Den Namespace System.Runtime.InteropServices einbinden!)

EWeiss 11. Apr 2015 21:53

AW: Zugriff auf Struct
 
Ist das jetzt Delphi C#?
Oder MS -> C#

Wenn Delphi dann kann ich es nicht verwenden.

Danke

gruss

jfheins 11. Apr 2015 22:02

AW: Zugriff auf Struct
 
Was ist "Delphi C#" ? :gruebel:

Mein Code oben ist normaler C# Code, der hier in der DP leider kein Highlighting hat. Die Funktion PtrToStructure solltest du auf jeden Fall verwenden können, wenn du auch PtrToStringAuto verwenden kannst.

EWeiss 11. Apr 2015 22:05

AW: Zugriff auf Struct
 
Zitat:

Zitat von jfheins (Beitrag 1297271)
Was ist "Delphi C#" ? :gruebel:

Mein Code oben ist normaler C# Code, der hier in der DP leider kein Highlighting hat. Die Funktion PtrToStructure solltest du auf jeden Fall verwenden können, wenn du auch PtrToStringAuto verwenden kannst.

ops.. gibt es kein CSharp für Delphi_Net?
Oder überhaupt keine NET unter Delphi dachte hab da mal was gelesen.

Ok danke muss mal schaun wie ich da was zaubern kann finde im Moment keinen Bezug zu meinem Code
abgesehen von PtrToStructure was natürlich Verwendung finden kann.

EDIT:
Sehe schon das wird wieder mal schwierig.

Code:
        Dim AudioAttributesPtr As IntPtr = IntPtr.Zero
        Dim AudioAttributes As New TAudioAttributes

        If TagsLib.TagsLibrary_GetAudioAttributes(hTags, TAudioType.atAutomatic, AudioAttributesPtr) Then
            txtChannels.Text = AudioAttributes.Channels.ToString
            txtSamplesPerSec.Text = AudioAttributes.SamplesPerSec.ToString
            txtBitsPerSample.Text = AudioAttributes.BitsPerSample.ToString
            txtPlayTime.Text = AudioAttributes.PlayTime.ToString
            txtSampleCount.Text = AudioAttributes.SampleCount.ToString
            txtBitRate.Text = AudioAttributes.Bitrate.ToString
        End If
aktuell bekomme ich bei
Code:
TagsLib.TagsLibrary_GetAudioAttributes(hTags, TAudioType.atAutomatic, AudioAttributesPtr)
eine Zugriffs Verletzung.
Zitat:

Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
logisch da der Pointer nicht zurückgegeben wird.


gruss

EWeiss 11. Apr 2015 23:19

AW: Zugriff auf Struct
 
Will irgendwie nicht

Code:
    public static bool TagsLibrary_GetAudioAttributes(HTAGS Tags, TAudioType AudioType, [In, Out, MarshalAs(UnmanagedType.AsAny)] IntPtr Attributes)
    {
      IntPtr ptr = TagsLibrary_GetAudioAttributesPtr(Tags, AudioType, Attributes);
      if (ptr != IntPtr.Zero)
      {
        return Convert.ToBoolean(Marshal.PtrToStructure(ptr, typeof(TagsLibraryDefs_API.TAudioAttributes)));
      }
      return false;
    }
    [DllImport("TagsLib.dll", EntryPoint = "TagsLibrary_GetAudioAttributes", CharSet = CharSet.Auto)]
    private static extern IntPtr TagsLibrary_GetAudioAttributesPtr(HTAGS Tags, TAudioType AudioType, [In, Out, MarshalAs(UnmanagedType.AsAny)] IntPtr Attributes);
Hmmm..
Zitat:

System.Runtime.InteropServices.MarshalDirectiveExc eption was unhandled
HResult=-2146233035
Message="parameter #3" kann nicht gemarshallt werden: Ungültige verwaltete/nicht verwaltete Typenkombination (Int/UInt muss mit SysInt oder SysUInt kombiniert werden)..
Source=TagsLibraryDefs.Net
StackTrace:
bei TagsLibraryDefs_API.TagsLib.TagsLibrary_GetAudioAt tributesPtr(HTAGS Tags, TAudioType AudioType, IntPtr Attributes)
gruss

EWeiss 12. Apr 2015 01:07

AW: Zugriff auf Struct
 
Funktioniert jetzt

Code:
  [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
  public struct TAudioAttributes
  {
    public int Channels;
    public int SamplesPerSec;
    public int BitsPerSample;
    public double PlayTime;
    public UInt64 SampleCount;
    public int Bitrate;
  }
Code:
    //TagsLibrary_GetAudioAttributes
    [DllImport("TagsLib.dll", EntryPoint = "TagsLibrary_GetAudioAttributes", CharSet = CharSet.Auto)]
    public static extern TTagError TagsLibrary_GetAudioAttributes(HTAGS Tags, TAudioType AudioType, ref TAudioAttributes Attributes);
War doch gar nicht so schwer.. LOL

gruss


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