J'ai une bibliothèque C que je souhaite utiliser depuis Octave . Suite au tutoriel a >, cela semble simple: enveloppez les fonctions en C ++ puis mkoctfile . Le problème est: que se passe-t-il si je souhaite avoir plusieurs définitions de fonctions (wrappers) dans un seul fichier source?
Dans le didacticiel mentionné, il est indiqué
Il faut noter qu'il est parfaitement acceptable d'avoir plus d'une fonction DEFUN_DLD dans un fichier source. Cependant, il doit y avoir soit un lien symbolique vers le fichier oct pour chacune des fonctions définies dans le code source avec la macro DEFUN_DLD ou l'autoload ( Function Files ) doit être utilisée.
Puis dans le lien fourni:
Une fois qu'Octave trouve un fichier avec un nom qui correspond (la fonction appelée), le contenu du fichier est lu. S'il définit une seule fonction, il est compilé et exécuté. Voir Fichiers de script , pour plus d'informations sur la peut définir plusieurs fonctions dans un seul fichier.
Dans ce deuxième lien, il n'y a aucune information sur la façon de charger un fichier .oct contenant plusieurs fonctions ou sur la façon de générer plusieurs fichiers .oct à partir d'un fichier source unique. D'après ce que j'ai compris, la dernière approche est la bonne. Comment puis-je faire ça?
4 Réponses :
Le but du deuxième lien est que vous ne chargez pas un fichier .oct contenant plusieurs fonctions - du moins pas du point de vue d'octave. C'est à cela que servent les liens symboliques - vous avez des symboles A
, B
et C
? Créez des liens symboliques A.oct
, B.oct
et C.oct
qui pointent vers ce fichier et vous pouvez les utiliser comme si chacun contenait seulement le symbole qui vous tient à cœur.
Veuillez noter que les liens symboliques sont à éviter dans les paquets Octave, car les liens symboliques n'existent pas sur certains systèmes de fichiers et donc le mécanisme de chargement automatique décrit par carandraug doit être préféré
Si vous avez plusieurs définitions de fonctions dans un seul fichier oct, vous utilisez autoload ()
. Donc, si vous avez foo.oct
qui a les fonctions foo
et bar
, alors vous faites:
autoload ("bar", "path-to-foo.oct");
p >
Cette citation de la documentation a clarifié cette réponse pour moi: "Normalement, les appels au chargement automatique apparaissent dans les fichiers de script PKG_ADD qui sont évalués lorsqu'un répertoire est ajouté au chemin de chargement d'Octave."
@CrisLuengo: voir également / doc / interpreter /… . De nos jours, presque tous les paquets de forge d'octave ont la directive PKG_ADD dans les fichiers source et pkg
crée le PKG_ADD lors de l'installation
Je vais commencer par clarifier la deuxième fenêtre de citation dans votre question. Cela ne fait pas spécifiquement référence aux fonctions définies par .oct. Ce que cela implique, c'est la différence entre une fonction définie par fichier m canonique et des fonctions «sur place» définies directement dans la console ou dans le cadre d'un script.
En ce qui concerne la première fenêtre de guillemets, en ce qui concerne les fonctions définies dans les fichiers .oct, la situation est différente. Ce qu'il dit, c'est que vous pouvez créer un fichier .oct qui définit de nombreuses fonctions, mais pour appeler ces fonctions, il doit y avoir un fichier du même nom dans ton chemin. Donc, si un fichier .oct définit les fonctions "foo" et "bar", vous devez avoir une copie du fichier .oct appelée "foo.oct", et une autre (ou, plus réaliste, comme lien symbolique vers l'original) renommée comme "bar.oct".
De même, vous pouvez également définir un fichier "foo.m" et "bar.m" dans votre espace de travail, qui ne contient que la documentation de ces fonctions, de sorte que si vous faites ensuite "help foo" ou "help bar" vous obtenez la documentation prévue.
Vous pouvez également utiliser autoload , comme l'a suggéré carandraug.
Une autre possibilité de générer une interface C à Octave consiste à utiliser SWIG qui peut générer un seul fichier .oct avec toutes vos fonctions. Reportez-vous à ici lorsque vous utilisez des pointeurs et des tableaux.
Voici un exemple:
header
% File test.m swigexample; fact(5) fact2(4,4) % ============== a = new_intp(); intp_assign(a, 37); b = new_intp(); intp_assign(b, 22); c = new_intp(); add(a,b,c); r = intp_value(c); delete_intp(a); delete_intp(b); delete_intp(c); r
source
swig -octave -o swigexample.cpp example.i mkoctfile -I. -I/usr/include/octave-4.2.2/ -Iswiglib swigexample.cpp example.c
interface
/* File example.i */ %module swigexample %include "cpointer.i" %{ #include "example.h" %} %pointer_functions(int, intp) %include "example.h"
compile
/* File: example.c */ #include "example.h" int fact(int n) { if (n < 0){ /* This should probably return an error, but this is simpler */ return 0; } if (n == 0) { return 1; } else { /* testing for overflow would be a good idea here */ return n * fact(n-1); } } int fact2(int n1, int n2) { return fact(n1)*fact(n2); } void add(int *x, int *y, int *r) { *r = *x + *y; }
test
/* File: example.h */ int fact(int n); int fact2(int n1, int n2); void add(int *x, int *y, int *r);