Cpp Struktur mit Funktionszeiger in C#?

Hallo liebe Community, ich bins mal wieder.
Da VC++ bei mir endgültig verbuggt, versuche ich nun einen Wrapper C#-Only zu erstellen.

Folgende C++ Struktur wird benötigt:
C++:
typedef struct SDL_AudioCVT
{
    int needed;                 /**< Set to 1 if conversion possible */
    SDL_AudioFormat src_format; /**< Source audio format */
    SDL_AudioFormat dst_format; /**< Target audio format */
    double rate_incr;           /**< Rate conversion increment */
    Uint8 *buf;                 /**< Buffer to hold entire audio data */
    int len;                    /**< Length of original audio buffer */
    int len_cvt;                /**< Length of converted audio buffer */
    int len_mult;               /**< buffer must be len*len_mult big */
    double len_ratio;           /**< Given len, final size is len*len_ratio */
    SDL_AudioFilter filters[10];        /**< Filter list */
    int filter_index;           /**< Current audio conversion function */
} SDL_AUDIOCVT_PACKED SDL_AudioCVT;

So sieht der Funktionszeiger momentan aus:
C++:
typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt, SDL_AudioFormat format);

Meine funktionierende Equivalent-Struktur sieht so aus:
C#:
public struct AudioCVT
{
    public int Needed;
    public ushort SrcFormat;
    public ushort DstFormat;
    public double RateIncr;
    public byte* Buf;
    public int Len;
    public int LenCvt;
    public int LenMult;
    public double LenRation;
    public IntPtr[] Filters;
    public int FilterIndex;
}

Mir gefällt allerdings nicht, dass ich die Funktionszeiger als IntPtr habe, jedoch weiß ich nicht, wie ich das sonst machen soll.

Weiß da jemand, wie ich das machen kann?

Danke schon mal im Voraus.
Gr. JustShinigami
 
Hey Spyke,
ja das kenn ich schon. Ich bevorzuge allerdings lieber selbstgeschriebenes, damit ich lerne. Im Prinzip könnte ich auch die Library aus deinem Link nehmen, aber was würde ich dann übers wrappen lernen? Was ist, wenn ich eine C++ Library brauche, die noch nicht gewrappt wurde? Also im großen und ganzen ist das Wrappen von SDL momentan mehr ein Lernstadium als eine Notwendigkeit. Ich könnte mein Problem auch umgehen, würde aber den Codeaufwand nochmal erhöhen. Deshalb frage ich hier nach, da sich hier ja vielleicht einige damit auskennen :)

Gr. JustShinigami
 

deepthroat

Erfahrenes Mitglied
Hi.

Du mußt ein delegate für den Funktionszeiger definieren:
C#:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int aFuncPtr(int x, int y);
 
Hallo Deepthroat. Ich wollte deinen Code wohl testen, jedoch habe ich das Problem, dass ich keinen Pointer von AudioCVT erstellen kann, wenn ich da delegates benutze. Das wird wohl daran liegen, dass Delegaten eine Ableitung von der Klasse Delegate sind und gleichzeitig ein Refferenztyp. Das führt dazu, dass ein Pointer auf eine Struktur, die eine Refferenz beinhaltet, nicht angenommen wird. Müsste ich dann also immer IntPtr in meinen Delegaten konvertieren, bevor ich die Methode aufrufen kann?

Gruß, JustShinigami
 

deepthroat

Erfahrenes Mitglied
Hallo Deepthroat. Ich wollte deinen Code wohl testen, jedoch habe ich das Problem, dass ich keinen Pointer von AudioCVT erstellen kann, wenn ich da delegates benutze. Das wird wohl daran liegen, dass Delegaten eine Ableitung von der Klasse Delegate sind und gleichzeitig ein Refferenztyp. Das führt dazu, dass ein Pointer auf eine Struktur, die eine Refferenz beinhaltet, nicht angenommen wird. Müsste ich dann also immer IntPtr in meinen Delegaten konvertieren, bevor ich die Methode aufrufen kann?
Zeig deinen Code und die Fehlermeldungen.
 
Nicht funktionierende Struktur:
C#:
public struct AudioCVT
{
    public int Needed;
    public ushort SrcFormat;
    public ushort DstFormat;
    public double RateIncr;
    public byte* Buf;
    public int Len;
    public int LenCvt;
    public int LenMult;
    public double LenRation;
    public IntPtr[] Filters; // <-- Hier kommt die Fehlermeldung, die ich nachher aufschreibe.
    public int FilterIndex;
}

Funktionierende Struktur:
C#:
public struct AudioCVT
{
    public int Needed;
    public ushort SrcFormat;
    public ushort DstFormat;
    public double RateIncr;
    public byte* Buf;
    public int Len;
    public int LenCvt;
    public int LenMult;
    public double LenRation;
    public IntPtr* Filters; // <-- Als Pointer funktioniert es, auch wenn ich Pointer als Array nicht leiden kann..
    public int FilterIndex;
}

Nicht funktionierende Struktur mit Delegaten:
C#:
public struct AudioCVT
{
    public int Needed;
    public ushort SrcFormat;
    public ushort DstFormat;
    public double RateIncr;
    public byte* Buf;
    public int Len;
    public int LenCvt;
    public int LenMult;
    public double LenRation;
    public AudioFilter* Filters; // <-- Hier kommt der Fehler.
    public int FilterIndex;
}

Mein Delegat sieht so aus:
C#:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate void AudioFilter(AudioCVT* CVT, ushort Format);

Die Fehlermeldung der IntPtr Array Struktur sieht wie folgt aus:
Code:
Es ist nicht möglich, einen Zeiger für den verwalteten Typ ("SG.Framework.SDL.Core32.SDL.AudioCVT") zu deklarieren oder dessen Adresse oder Größe abzurufen

Die Fehlermeldung der Delegat Struktur sieht wie folgt aus:
Code:
Es ist nicht möglich, einen Zeiger für den verwalteten Typ ("SG.Framework.SDL.Core32.SDL.AudioFilter") zu deklarieren oder dessen Adresse oder Größe abzurufen.

Ist alles etwas umständlich, ich weiß, aber ich will halt nicht ständig im Code Marshal.GetDelegateForFunctionPointer(...) benutzen.

Wenn keinem eine Lösung einfällt, werd ich wohl auf eine kleine statische HelperFunction zugreifen müssen, die ich selbst schreibe, wo die IntPtr intern in den Delegaten konvertiert werden und aufgerufen werden :/ (Meine nächste Lösung für das Problem, allerdings auch nicht allzu sauber ;s)

Gruß, JustShinigami