6
votes

Appeler des fonctions C ++ contenant des rappels dans C #

hey tout im essayant d'obtenir ma tête autour de cette fonction C ++ en C #: xxx

Ceci est issu d'une API Winradio trouvé ici http://www.winradio.com/home/g305_sdk.htm .

J'ai trouvé que d'autres personnes ont demandé à propos de appeler cette fonction spécifique sur le net et ils avaient: xxx

mais je ne peux pas comprendre comment implémenter cela plus loin.

Toutes les pensées ou les indications sur Comment appeler cela?

Merci beaucoup


1 commentaires

3 Réponses :



0
votes

Tout ce que vous avez à faire est de créer une fonction C # qui correspond à la signature du délégué que vous avez déclaré. Créez un délégué, déposez-vous à une référence à ce délégué afin qu'il ne reçoive pas de déchets collectés et appelez l'importation de la DLL avec le délégué comme rappel.

Donc, vous receviez quelque chose comme ceci: P>

public void MyCallback(IntPtr P)
{
    //do something
}

// somewhere else in your code
var cb = new CallbackFunc(MyCallback);
CodecStart(..., cb, ...);


0 commentaires

5
votes

Voici une simple implémentation qui la mettra tous ensemble.

class WinRadioWrapper
{
    public delegate void CallbackFunc( IntPtr pData );

    [DllImport( "WRG305API.dll" )]
    public static extern bool CodecStart( int hRadio, CallbackFunc func, IntPtr CallbackTarget );

    public bool CodecStartTest(int hRadio)
    {
        bool bStarted = CodecStart( hRadio, MyCallbackFunc, IntPtr.Zero );
        return bStarted;
    }

    // Note: this method will be called from a different thread!
    static void MyCallbackFunc( IntPtr pData )
    {
        // Sophisticated work goes here...
    }
}
  • Notez que parce que myCallbackfunc code> sera exécuté sur un thread différent, j'ai choisi de faire est statique code>. De cette façon, vous ne serez pas tenté d'accéder à Winradiowrapper code> Membres de données. P> LI>

  • pour la simplicité, j'ai passé un paramètre intptr.zero code> sur le rappel, mais cela peut indiquer toutes les données que vous souhaitez utiliser dans le rappel.

    [Veuillez ignorer ce paragraphe] strong> regarder dans marshal.structuretoptr code> si vous souhaitez transmettre des données au rappel, mais assurez-vous également PIN Les données que vous passez pour vous assurer que ce n'est pas collecté à la poubelle (voir gchandle code> pour plus de détails). em> p> l> l> l> ul>

    EDIT: strong>
    avec les mots intéressants de svick (merci!), je me rendais compte que je mélangeais un objet copié avec une épinglée .
    donc, pour trier les choses: p>

    • marshal.structuretoptr code> doit être utilisé si vous souhaitez copier une structure de données existante, puis transmettez-la à la fonction de rappel. Li>
    • Si, d'autre part, vous souhaitez utiliser une structure de données existante (par exemple, pour modifier son contenu), vous devez utiliser gchandle code> afin de broche em > C'est en mémoire et empêchez-le d'être collectés à la poubelle.
      Toutefois, il ya ajouter une augmentation de la maintenance pour le gchandle code>. li> ul> p>


5 commentaires

Vous n'avez pas besoin de broder les données que vous passez à structuretoptr () , car elle crée une copie de l'objet.


Que se passe-t-il si vous souhaitez transmettre le cette instance de classe comme intptr ?


Vous voulez dire sans copier? Vous ne pouvez pas faire ça, je pense.


Des trucs importants .. Je mettrai à jour ma réponse. Merci pour la séance d'ouverture des yeux.


J'ai un problème similaire sauf mon rappel retourne toujours 1 ..... lien