Introduction

Ce didacticiel est destiné aux utilisateurs maîtrisant la programmation en C ou C++, ainsi que l'architecture de la Simple Virtual Machine.

Dans ce didacticiel, vous allez créer et manipuler des structures d'extension de la machine virtuelle.

Le temps de lecture de ce didacticiel est estimé à 25 minutes.

Mise en place

Pour commencer, créez le canevas de l'extension dans le fichier structures.svm_plugin en utilisant ce code :

PLUGIN struct

DEFINE

Définition

Une structure d'extension est un conteneur de données réservé aux extensions. En particulier, une structure ne peut pas être écrite en mémoire, et ne peut pas apparaître en tant qu'argument d'instruction.

Un point important doit être mentionné : même si l'existence d'une structure d'extension est publique au sein de la machine virtuelle (les autres extensions en connaissent l'existence), le contenu de la structure en C/C++ doit être en général considéré comme privé à l'extension qui la définit.

Structure

La première chose qu'une structure définit, c'est le conteneur de données lui-même.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	int _i;
	std::string _s;
%}

Cette définition, très proche de celle d'un type, permet de définir la struct C/C++ qui a pour type le nom formé de la chaine fixe "struct_" suivie du nom de l'entrée de la structure.

Destruction

La seule fonction obligatoire pour une structure est sa fonction de destruction.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	int _i;
	std::string _s;
%}
delete default: %{}

Copie

La seconde fonction, optionnelle, permet d'activer la copie d'une structure.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	int _i;
	std::string _s;
%}
delete default: %{}
copy default: %{}

Générez et compilez l'extension. Pour l'instant, l'utilisation de cette extension est ultra réduite, et écrire une application avec n'est guère utile.

Opérations

Création

La création d'une structure, au delà de celle en C/C++, se fait via l'interface programmatique.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	int _i;
	std::string _s;
%}
delete default: %{}
copy default: %{}

INSTRUCTION struct.example
%{
	auto rs = new struct_instance { 17, "text" };
	SVM_Structure s = ::svm_structure_new(svm,CONST_PEP(struct,instance),rs);
%}

Vous pouvez générer et compiler cette extension, mais son utilisation n'est guère spectaculaire.

Notez cependant la similarité entre l'appel à la fonction svm_structure_new et celle utilisée pour les types extension svm_value_plugin_new.

Copie

La fonction de destruction d'une structure est automatiquement appellée par la machine virtuelle lorsque la structure n'est plus utile. La fonction de copie, quant à elle, n'est jamais appellée par la machine virtuelle : elle ne peut être appellée qu'explicitement via l'interface programmatique.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	int _i;
	std::string _s;
%}
delete default: %{}
copy default: %{}

INSTRUCTION struct.example
%{
	auto rs = new struct_instance { 17, "text" };
	SVM_Structure s = ::svm_structure_new(svm,CONST_PEP(struct,instance),rs);
	SVM_Structure c = ::svm_structure_copy(svm,s);
%}

Vous pouvez générer et compiler cette extension, mais son utilisation n'est toujours pas spectaculaire.

Introspection

Il est possible à partir d'une structure de récupérer son type et le pointeur vers la structure C/C++ contenue dans la structure.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	int _i;
	std::string _s;
%}
delete default: %{}
copy default: %{}

INSTRUCTION struct.example
%{
	auto rs = new struct_instance { 17, "text" };
	SVM_Structure s = ::svm_structure_new(svm,CONST_PEP(struct,instance),rs);
	SVM_Structure c = ::svm_structure_copy(svm,s);
	SVM_Value_PluginEntryPoint type = ::svm_structure_get_type(svm,c);
	struct_instance *i = reinterpret_cast<struct_instance*>(::svm_structure_get_internal(svm,CONST_PEP(struct,instance),c));
	i->_i = 42;
%}

La fonction svm_structure_get_type permet de récupérer le type d'une structure sous la forme d'un point d'entrée d'extension. De même, la fonction svm_structure_get_internal permet de récupérer le pointeur sur la structure C/C++ conservée par la structure. Notez la présence du type dans cette fonction, qui sert de garant pour la validité de l'appel au reinterpret_cast du C++.

Vous pouvez générer et compiler cette extension, mais son utilisation ne présente toujours pas un grand intérêt.

Usages

Les usages d'une structure d'extension peuvent être multiples, et le présent didacticiel ne saurait toutes les décrire. Cependant, certains usages caractéristiques des structures méritent une attention particulière.

Composition de type

La première utilisation est la composition de type : il s'agit de définir un type dont une ou plusieurs parties sont des structures, pour rendre ce type polymorphe.

Modifiez le code de l'extension :

PLUGIN struct

DEFINE

STRUCT struct.instance
%{
	long long int _i;
	std::string _s;
%}
delete default: %{}
copy default: %{}

TYPE struct.interface
%{
	bool _b;
	SVM_Structure _s;
%}
delete default:
%{
	VARIABLE_LOCAL(object->_s);
%}
copy object:
%{
	auto c = new type_interface;
	c->_b = object->_b;
	c->_s = ::svm_structure_copy(svm,object->_s);
	VARIABLE_GLOBAL(c->_s);
	return c;
%}

INSTRUCTION struct.new BLN INT STR -> struct.interface
%{
	auto b = ARGV_VALUE(0,boolean);
	auto i = ARGV_VALUE(1,integer);
	auto s = ARGV_VALUE(2,string);
	auto t = new type_interface;
	t->_b = b==TRUE;
	auto rs = new struct_instance { i , RAW_STRING(s) };
	t->_s = ::svm_structure_new(svm,CONST_PEP(struct,instance),rs);
	VARIABLE_GLOBAL(t->_s);
	return NEW_PLUGIN(struct,interface,t);
%}

Dans cet exemple, la composition est limitée. Mais dans un didacticiel à venir, un autre objet des extensions va rendre cela beaucoup plus utile : lorsque cette construction est poussée à ses limites, on obtient le type com.device qui est une interface ultra-générique pour réaliser des entrées/sorties.

Générez et compilez l'extension. Vous pouvez créer une petite application qui crée une valeur du type struct.interface. Vous pouvez améliorer l'extension pour afficher l'ensemble de la valeur.

Notez que pour la composition soit fonctionnelle, il est impératif de rendre globale la variable Simple Virtual Machine de la structure. De la même manière, une structure extension qui contient des variables Simple Virtual Machine peut être amenée à rendre ces variables globales le temps de l'existence de la structure.

Paramètre d'interface programmatique

Les structures sont également utilisées par l'interface programmatique de la machine virtuelle pour spécifier d'une manière générique (mais toutefois contrôlée par la machine virtuelle) des valeurs utilisateur.

Des exemples de cet usage seront présentés dans un didacticiel ultérieur.

Conclusion

Vous venez de voir comment créer et manipuler les structures extensions depuis une extension.

Les structures sont un concept relativement pauvre en eux-mêmes, et vont prendre toute leur importance avec un autre concept des extensions qui sera abordé dans un prochain didacticiel.

Combinée correctement avec les autres objets des extensions, les structures apportent une flexibilité très intéressante dans l'écriture des extensions.