2009-09-24 10 views
2

J'ai déployé un projet MATLAB dans une DLL, à appeler à partir de C++, et cela fonctionne très bien. Jours heureux.Comment annuler une fonction de fichier m MATLAB à partir de C/C++?

Mais que se passe-t-il lorsque l'utilisateur demande d'annuler une opération? J'ai essayé de créer une variable global nommée UserAborted. Je l'initialise à 0 avant d'exécuter la longue fonction dans MATLAB. J'ai écrit aussi les deux fonctions suivantes:

function AbortIfUserRequested 
    global UserAborted 

    if (UserAborted == 1) 
     error('User Abort'); 
    end 
end 

function UserAbortLongFunction 
    global UserAborted 

    UserAborted = 1; 
end 

Je demande à AbortIfUserRequested dans chaque itération de la boucle dans ma longue fonction. J'ai également exporté UserAbortLongFunction.

Je m'attendais à ce que peu de temps après appelé UserAbortLongFunction, la fonction longue atteindrait un appel à AbortIfUserRequested, et lancer une erreur. Au lieu de cela, la fonction longue continue à fonctionner jusqu'à la fin, et seulement puis change la valeur de UserAborted.

Tout ce que je veux faire, c'est annuler cette longue fonction quand l'utilisateur me le demande! Y'a-t'il un quelconque moyen d'y arriver?

+0

Matlab est monothread du point de vue du code M. Comment appelez-vous UserAbortLongFunction? Est-ce que UserAbortLongFunction retourne pendant que l'opération longue est toujours en cours ou bloque? –

+0

L'appel de 'UserAbortLongFunction' ne bloque pas, et retourne immédiatement. Je ne suis pas sûr que ce soit un problème de code M; J'ai essayé d'exécuter 'UserAbortLongFunction' à partir de la ligne de commande dans MATLAB pendant que la fonction longue était en cours d'exécution. J'ai aussi eu la fonction longue imprimer la valeur de 'UserAborted' dans le cadre de son fonctionnement, à de nombreux points dans le code. Il est resté 0 jusqu'à la fin de la longue fonction, longtemps après avoir appelé 'UserAbortLongFunction'. – scraimer

Répondre

1

Matlab doit fournir des fonctions de rappel pour montrer la progression de l'exécution et éventuellement l'arrêter. Une recherche Google montre beaucoup de gens qui veulent cela, mais aucune implémentation de Mathworks.

+0

Hmm ... Bon point. Mais vous savez, MATLAB a quelques fonctions de rappel - pour la sortie standard et l'erreur standard. J'ai simplement fait 'disp ('PROGRESS = 33%)' et cela a appelé la fonction de rappel pour gérer l'erreur standard.Ensuite, j'ai juste analysé ces chaînes, et affiché la progression dans l'interface graphique C++. Mais vous avez raison - il n'y a pas de soutien approprié. – scraimer

1

La nature monothread de Matlab peut empêcher la mise à jour de la valeur de la variable globale de se propager lorsque la première fonction est en cours d'exécution. Vous pouvez essayer de coller l'indicateur d'abandon dans un objet Java, comme un HashMap, pour une couche d'indirection. Étant donné que les objets Java sont transmis par référence, une mise à jour de leur état peut être immédiatement visible, sans nécessiter de modification de la variable Matlab elle-même.

Voici un extrait de ce document. (Désolé, je n'ai pas de licence compilateur Matlab pour tester ceci dans une DLL déployée.)

function AbortIfUserRequested 
    global SharedState 
    if SharedState.get('UserAborted') 
     error('User Abort'); 
    end 
end 

function UserAbortLongFunction 
    global SharedState 
    SharedState.put('UserAborted', 1); 
end 

function InitUserAbort 
    global SharedState 
    SharedState = java.util.Collections.synchronizedMap(java.util.HashMap()); 
    SharedState.put('UserAborted', 0); 
end 

données app Matlab est aussi efficace passé par référence. Mettre l'indicateur d'abandon dans appdata au lieu d'une variable globale pourrait aussi fonctionner. Si votre bibliothèque fonctionne avec une interface graphique Matlab, vous pouvez placer les données de l'application sur son handle de figure à la place du handle global 0. Ce serait Matlab plus idiomatique que l'objet Java, si cela fonctionne.

function AbortIfUserRequested 
    if getappdata(0, 'UserAborted') 
     error('User Abort'); 
    end 
end 
function UserAbortLongFunction 
    setappdata(0, 'UserAborted', 1); 
end 
5

Essayez d'appeler la fonction DRAWNOW dans AbortIfUserRequested. Bien que Matlab soit monothread (du point de vue de l'API), il autorise les interruptions. J'ai eu du succès en appelant cette fonction avec du code M pur où l'entrée de l'utilisateur (comme Ctrl-C) se verrouille autrement.

Questions connexes