/// This file has been generated, if you wish to
/// modify it in a permanent way, please refer
/// to the script file : gen/generator_cs.rb

#include "interface.hh"

#include <iostream>
#include <assert.h>
#include <cstdlib>
#include <cstring>

CSharpInterface gl_csharp;

template < class Out, class Cxx >
Out cxx2lang(Cxx in)
{
  return (Out)in;
}

template <>
MonoString* cxx2lang<MonoString*, std::string>(std::string in)
{
  return mono_string_new (gl_csharp.getDomain(), in.c_str());
}

template <>
gint32 cxx2lang< gint32, int >(int in)
{
  return (gint32)in;
}

template <>
gint32 cxx2lang< gint32, bool >(bool in)
{
  return (gint32)in;
}

template < class Out, class Cxx >
Cxx lang2cxx(Out in)
{
  return (Cxx)in;
}

template <>
std::string lang2cxx< MonoString*, std::string >(MonoString* in)
{
  std::string s_out;
  MonoError error;
  char *c_out;

  if (!in)
    return std::string("(null)");
  c_out = mono_string_to_utf8_checked(in, &error);
  if (!mono_error_ok(&error)) {
    s_out = std::string(mono_error_get_message(&error));
    mono_error_cleanup(&error);
    return s_out;
  } else {
    s_out = std::string(c_out);
    mono_free(c_out);
    return s_out;
  }
}

template <>
int lang2cxx< gint32, int >(gint32 in)
{
  return (int)in;
}

template <>
bool lang2cxx< gint32, bool >(gint32 in)
{
  return (bool)in;
}

template <>
MonoArray* cxx2lang< MonoArray*, std::vector<int> >(std::vector<int> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_get_int32_class();
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);

  for (int i = 0; i < size; ++i)
    mono_array_set(maArray, gint32, i, (cxx2lang< gint32, int >(in[i])));

  return maArray;
}

template <>
std::vector<int> lang2cxx< MonoArray*, std::vector<int> >(MonoArray* in)
{
  std::vector< int > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< gint32, int >(mono_array_get(in, gint32, i)));

  return out;
}
/// Types de cases
template <>
gint32 cxx2lang< gint32, case_type >(case_type in)
{
  return (gint32)in;
}

template <>
case_type lang2cxx< gint32, case_type >(gint32 in)
{
  return (case_type)in;
}
template <>
MonoArray* cxx2lang< MonoArray*, std::vector<case_type> >(std::vector<case_type> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "CaseType");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_set(maArray, gint32, i, (cxx2lang< gint32, case_type >(in[i])));
  return maArray;
}

template <>
std::vector<case_type> lang2cxx< MonoArray*, std::vector<case_type> >(MonoArray* in)
{
  std::vector< case_type > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< gint32, case_type >(mono_array_get(in , gint32, i)));
  return out;
}

/// Types de propriétés des éléments
template <>
gint32 cxx2lang< gint32, element_propriete >(element_propriete in)
{
  return (gint32)in;
}

template <>
element_propriete lang2cxx< gint32, element_propriete >(gint32 in)
{
  return (element_propriete)in;
}
template <>
MonoArray* cxx2lang< MonoArray*, std::vector<element_propriete> >(std::vector<element_propriete> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "ElementPropriete");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_set(maArray, gint32, i, (cxx2lang< gint32, element_propriete >(in[i])));
  return maArray;
}

template <>
std::vector<element_propriete> lang2cxx< MonoArray*, std::vector<element_propriete> >(MonoArray* in)
{
  std::vector< element_propriete > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< gint32, element_propriete >(mono_array_get(in , gint32, i)));
  return out;
}

/// Erreurs possibles
template <>
gint32 cxx2lang< gint32, erreur >(erreur in)
{
  return (gint32)in;
}

template <>
erreur lang2cxx< gint32, erreur >(gint32 in)
{
  return (erreur)in;
}
template <>
MonoArray* cxx2lang< MonoArray*, std::vector<erreur> >(std::vector<erreur> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Erreur");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_set(maArray, gint32, i, (cxx2lang< gint32, erreur >(in[i])));
  return maArray;
}

template <>
std::vector<erreur> lang2cxx< MonoArray*, std::vector<erreur> >(MonoArray* in)
{
  std::vector< erreur > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< gint32, erreur >(mono_array_get(in , gint32, i)));
  return out;
}

/// Types d’actions
template <>
gint32 cxx2lang< gint32, action_type >(action_type in)
{
  return (gint32)in;
}

template <>
action_type lang2cxx< gint32, action_type >(gint32 in)
{
  return (action_type)in;
}
template <>
MonoArray* cxx2lang< MonoArray*, std::vector<action_type> >(std::vector<action_type> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "ActionType");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_set(maArray, gint32, i, (cxx2lang< gint32, action_type >(in[i])));
  return maArray;
}

template <>
std::vector<action_type> lang2cxx< MonoArray*, std::vector<action_type> >(MonoArray* in)
{
  std::vector< action_type > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< gint32, action_type >(mono_array_get(in , gint32, i)));
  return out;
}

/// Position sur la carte, donnée par deux coordonnées
template <>
MonoObject* cxx2lang< MonoObject*, position >(position in)
{
  MonoClass*  mcKlass  = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Position");
  MonoObject* moObj    = mono_object_new(gl_csharp.getDomain(), mcKlass);
mono_runtime_object_init(moObj);
  auto arg_ligne = cxx2lang< gint32, int >(in.ligne);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Ligne"), &arg_ligne);
  auto arg_colonne = cxx2lang< gint32, int >(in.colonne);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Colonne"), &arg_colonne);
  return moObj;
}

template <>
position lang2cxx< MonoObject*, position >(MonoObject* in)
{
    position out;
  void*      field_out;
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Position");
  (void)field_out;
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Ligne"), &out.ligne);
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Colonne"), &out.colonne);
  return out;
}

template <>
MonoArray* cxx2lang< MonoArray*, std::vector<position> >(std::vector<position> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Position");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_setref(maArray, i, (cxx2lang< MonoObject*, position >(in[i])));
  return maArray;
}

template <>
std::vector<position> lang2cxx< MonoArray*, std::vector<position> >(MonoArray* in)
{
  std::vector< position > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< MonoObject*, position >(reinterpret_cast<MonoObject*>(mono_array_get(in, MonoObject*, i))));
  return out;
}

/// Échantillon, défini par deux types d’éléments
template <>
MonoObject* cxx2lang< MonoObject*, echantillon >(echantillon in)
{
  MonoClass*  mcKlass  = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Echantillon");
  MonoObject* moObj    = mono_object_new(gl_csharp.getDomain(), mcKlass);
mono_runtime_object_init(moObj);
  auto arg_element1 = cxx2lang< gint32, case_type >(in.element1);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Element1"), &arg_element1);
  auto arg_element2 = cxx2lang< gint32, case_type >(in.element2);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Element2"), &arg_element2);
  return moObj;
}

template <>
echantillon lang2cxx< MonoObject*, echantillon >(MonoObject* in)
{
    echantillon out;
  void*      field_out;
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Echantillon");
  (void)field_out;
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Element1"), &out.element1);
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Element2"), &out.element2);
  return out;
}

template <>
MonoArray* cxx2lang< MonoArray*, std::vector<echantillon> >(std::vector<echantillon> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "Echantillon");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_setref(maArray, i, (cxx2lang< MonoObject*, echantillon >(in[i])));
  return maArray;
}

template <>
std::vector<echantillon> lang2cxx< MonoArray*, std::vector<echantillon> >(MonoArray* in)
{
  std::vector< echantillon > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< MonoObject*, echantillon >(reinterpret_cast<MonoObject*>(mono_array_get(in, MonoObject*, i))));
  return out;
}

/// Position d’un échantillon, donnée par deux positions adjacentes
template <>
MonoObject* cxx2lang< MonoObject*, position_echantillon >(position_echantillon in)
{
  MonoClass*  mcKlass  = mono_class_from_name(gl_csharp.getImage(), "Prologin", "PositionEchantillon");
  MonoObject* moObj    = mono_object_new(gl_csharp.getDomain(), mcKlass);
mono_runtime_object_init(moObj);
  auto arg_pos1 = cxx2lang< MonoObject*, position >(in.pos1);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Pos1"), &arg_pos1);
  auto arg_pos2 = cxx2lang< MonoObject*, position >(in.pos2);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Pos2"), &arg_pos2);
  return moObj;
}

template <>
position_echantillon lang2cxx< MonoObject*, position_echantillon >(MonoObject* in)
{
    position_echantillon out;
  void*      field_out;
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "PositionEchantillon");
  (void)field_out;
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Pos1"), &field_out);
  out.pos1 = lang2cxx< MonoObject*, position >(reinterpret_cast< MonoObject* >(field_out));
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Pos2"), &field_out);
  out.pos2 = lang2cxx< MonoObject*, position >(reinterpret_cast< MonoObject* >(field_out));
  return out;
}

template <>
MonoArray* cxx2lang< MonoArray*, std::vector<position_echantillon> >(std::vector<position_echantillon> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "PositionEchantillon");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_setref(maArray, i, (cxx2lang< MonoObject*, position_echantillon >(in[i])));
  return maArray;
}

template <>
std::vector<position_echantillon> lang2cxx< MonoArray*, std::vector<position_echantillon> >(MonoArray* in)
{
  std::vector< position_echantillon > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< MonoObject*, position_echantillon >(reinterpret_cast<MonoObject*>(mono_array_get(in, MonoObject*, i))));
  return out;
}

/// Action représentée dans l’historique. L’action ``placer_echantillon`` utilise ``pos1`` et ``pos2``. L’action ``transmuter`` utilise ``pos1``. L’action ``catalyser`` utilise ``pos1``, ``id_apprenti`` et ``nouvelle_case``. L’action ``donner_echantillon`` n’est pas représentée dans l’historique, car ``echantillon_tour`` donne l’information.
template <>
MonoObject* cxx2lang< MonoObject*, action_hist >(action_hist in)
{
  MonoClass*  mcKlass  = mono_class_from_name(gl_csharp.getImage(), "Prologin", "ActionHist");
  MonoObject* moObj    = mono_object_new(gl_csharp.getDomain(), mcKlass);
mono_runtime_object_init(moObj);
  auto arg_atype = cxx2lang< gint32, action_type >(in.atype);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Atype"), &arg_atype);
  auto arg_pos1 = cxx2lang< MonoObject*, position >(in.pos1);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Pos1"), &arg_pos1);
  auto arg_pos2 = cxx2lang< MonoObject*, position >(in.pos2);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "Pos2"), &arg_pos2);
  auto arg_id_apprenti = cxx2lang< gint32, int >(in.id_apprenti);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "IdApprenti"), &arg_id_apprenti);
  auto arg_nouvelle_case = cxx2lang< gint32, case_type >(in.nouvelle_case);
  mono_field_set_value(moObj, mono_class_get_field_from_name(mcKlass, "NouvelleCase"), &arg_nouvelle_case);
  return moObj;
}

template <>
action_hist lang2cxx< MonoObject*, action_hist >(MonoObject* in)
{
    action_hist out;
  void*      field_out;
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "ActionHist");
  (void)field_out;
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Atype"), &out.atype);
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Pos1"), &field_out);
  out.pos1 = lang2cxx< MonoObject*, position >(reinterpret_cast< MonoObject* >(field_out));
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "Pos2"), &field_out);
  out.pos2 = lang2cxx< MonoObject*, position >(reinterpret_cast< MonoObject* >(field_out));
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "IdApprenti"), &out.id_apprenti);
  mono_field_get_value(in, mono_class_get_field_from_name(mcKlass, "NouvelleCase"), &out.nouvelle_case);
  return out;
}

template <>
MonoArray* cxx2lang< MonoArray*, std::vector<action_hist> >(std::vector<action_hist> in)
{
  gint32 size = in.size();
  MonoClass* mcKlass = mono_class_from_name(gl_csharp.getImage(), "Prologin", "ActionHist");
  MonoArray * maArray = mono_array_new(gl_csharp.getDomain(), mcKlass, size);
  for (int i = 0; i < size; ++i)
    mono_array_setref(maArray, i, (cxx2lang< MonoObject*, action_hist >(in[i])));
  return maArray;
}

template <>
std::vector<action_hist> lang2cxx< MonoArray*, std::vector<action_hist> >(MonoArray* in)
{
  std::vector< action_hist > out;
  gint32 size = mono_array_length(in);

  for (int i = 0; i < size; ++i)
    out.push_back(lang2cxx< MonoObject*, action_hist >(reinterpret_cast<MonoObject*>(mono_array_get(in, MonoObject*, i))));
  return out;
}

gint32 placer_echantillon(MonoObject* pos1, MonoObject* pos2)
{
	return cxx2lang< gint32, erreur >(api_placer_echantillon(lang2cxx< MonoObject*, position >(pos1), lang2cxx< MonoObject*, position >(pos2)))
;
}

gint32 transmuter(MonoObject* pos)
{
	return cxx2lang< gint32, erreur >(api_transmuter(lang2cxx< MonoObject*, position >(pos)))
;
}

gint32 catalyser(MonoObject* pos, gint32 id_apprenti, gint32 terrain)
{
	return cxx2lang< gint32, erreur >(api_catalyser(lang2cxx< MonoObject*, position >(pos), lang2cxx< gint32, int >(id_apprenti), lang2cxx< gint32, case_type >(terrain)))
;
}

gint32 donner_echantillon(MonoObject* echantillon_donne)
{
	return cxx2lang< gint32, erreur >(api_donner_echantillon(lang2cxx< MonoObject*, echantillon >(echantillon_donne)))
;
}

gint32 type_case(MonoObject* pos, gint32 id_apprenti)
{
	return cxx2lang< gint32, case_type >(api_type_case(lang2cxx< MonoObject*, position >(pos), lang2cxx< gint32, int >(id_apprenti)))
;
}

gint32 est_vide(MonoObject* pos, gint32 id_apprenti)
{
	return cxx2lang< gint32, bool >(api_est_vide(lang2cxx< MonoObject*, position >(pos), lang2cxx< gint32, int >(id_apprenti)))
;
}

gint32 propriete_case(MonoObject* pos, gint32 id_apprenti)
{
	return cxx2lang< gint32, element_propriete >(api_propriete_case(lang2cxx< MonoObject*, position >(pos), lang2cxx< gint32, int >(id_apprenti)))
;
}

gint32 propriete_case_type(gint32 ctype)
{
	return cxx2lang< gint32, element_propriete >(api_propriete_case_type(lang2cxx< gint32, case_type >(ctype)))
;
}

gint32 taille_region(MonoObject* pos, gint32 id_apprenti)
{
	return cxx2lang< gint32, int >(api_taille_region(lang2cxx< MonoObject*, position >(pos), lang2cxx< gint32, int >(id_apprenti)))
;
}

MonoArray* positions_region(MonoObject* pos, gint32 id_apprenti)
{
	return cxx2lang< MonoArray*, std::vector<position> >(api_positions_region(lang2cxx< MonoObject*, position >(pos), lang2cxx< gint32, int >(id_apprenti)))
;
}

gint32 placement_possible_echantillon(MonoObject* echantillon_a_placer, MonoObject* pos1, MonoObject* pos2, gint32 id_apprenti)
{
	return cxx2lang< gint32, bool >(api_placement_possible_echantillon(lang2cxx< MonoObject*, echantillon >(echantillon_a_placer), lang2cxx< MonoObject*, position >(pos1), lang2cxx< MonoObject*, position >(pos2), lang2cxx< gint32, int >(id_apprenti)))
;
}

MonoArray* placements_possible_echantillon(MonoObject* echantillon_a_placer, gint32 id_apprenti)
{
	return cxx2lang< MonoArray*, std::vector<position_echantillon> >(api_placements_possible_echantillon(lang2cxx< MonoObject*, echantillon >(echantillon_a_placer), lang2cxx< gint32, int >(id_apprenti)))
;
}

MonoArray* historique()
{
	return cxx2lang< MonoArray*, std::vector<action_hist> >(api_historique())
;
}

gint32 moi()
{
	return cxx2lang< gint32, int >(api_moi())
;
}

gint32 adversaire()
{
	return cxx2lang< gint32, int >(api_adversaire())
;
}

gint32 score(gint32 id_apprenti)
{
	return cxx2lang< gint32, int >(api_score(lang2cxx< gint32, int >(id_apprenti)))
;
}

gint32 tour_actuel()
{
	return cxx2lang< gint32, int >(api_tour_actuel())
;
}

gint32 annuler()
{
	return cxx2lang< gint32, bool >(api_annuler())
;
}

gint32 nombre_catalyseurs()
{
	return cxx2lang< gint32, int >(api_nombre_catalyseurs())
;
}

MonoObject* echantillon_tour()
{
	return cxx2lang< MonoObject*, echantillon >(api_echantillon_tour())
;
}

gint32 a_pose_echantillon()
{
	return cxx2lang< gint32, bool >(api_a_pose_echantillon())
;
}

gint32 a_donne_echantillon()
{
	return cxx2lang< gint32, bool >(api_a_donne_echantillon())
;
}

gint32 quantite_transmutation_or(gint32 taille_region)
{
	return cxx2lang< gint32, int >(api_quantite_transmutation_or(lang2cxx< gint32, int >(taille_region)))
;
}

gint32 quantite_transmutation_catalyseur(gint32 taille_region)
{
	return cxx2lang< gint32, int >(api_quantite_transmutation_catalyseur(lang2cxx< gint32, int >(taille_region)))
;
}

gint32 quantite_transmutation_catalyseur_or(gint32 taille_region)
{
	return cxx2lang< gint32, int >(api_quantite_transmutation_catalyseur_or(lang2cxx< gint32, int >(taille_region)))
;
}

MonoObject* echantillon_defaut_premier_tour()
{
	return cxx2lang< MonoObject*, echantillon >(api_echantillon_defaut_premier_tour())
;
}

void afficher_etablis()
{
	api_afficher_etablis()
;
}

void afficher_case_type(gint32 v)
{
	api_afficher_case_type(lang2cxx< gint32, case_type >(v))
;
}

void afficher_element_propriete(gint32 v)
{
	api_afficher_element_propriete(lang2cxx< gint32, element_propriete >(v))
;
}

void afficher_erreur(gint32 v)
{
	api_afficher_erreur(lang2cxx< gint32, erreur >(v))
;
}

void afficher_action_type(gint32 v)
{
	api_afficher_action_type(lang2cxx< gint32, action_type >(v))
;
}

void afficher_position(MonoObject* v)
{
	api_afficher_position(lang2cxx< MonoObject*, position >(v))
;
}

void afficher_echantillon(MonoObject* v)
{
	api_afficher_echantillon(lang2cxx< MonoObject*, echantillon >(v))
;
}

void afficher_position_echantillon(MonoObject* v)
{
	api_afficher_position_echantillon(lang2cxx< MonoObject*, position_echantillon >(v))
;
}

void afficher_action_hist(MonoObject* v)
{
	api_afficher_action_hist(lang2cxx< MonoObject*, action_hist >(v))
;
}


/*
** Inititialize Mono and load the DLL file.
*/
CSharpInterface::CSharpInterface()
{
  const char* champion_path = getenv("CHAMPION_PATH");
  std::string champion;

  if (!champion_path)
    champion = "./champion-prologin.dll";
  else
  {
    champion = champion_path;
    champion += "/champion-prologin.dll";
  }

  _domain = mono_jit_init(champion.c_str());
  assert(_domain != NULL);

  _assembly = mono_domain_assembly_open(_domain, champion.c_str());
  assert(_assembly != NULL);

  _image = mono_assembly_get_image(_assembly);
  assert(_image != NULL);

  _class = mono_class_from_name(_image, "Prologin", "Prologin");
  assert(_class != NULL);

  _object = mono_object_new(_domain, _class);
  assert(_object);

  mono_runtime_object_init(_object);

  // Register API functions as internal Mono functions
  mono_add_internal_call("Prologin.Api::PlacerEchantillon", (const void*)placer_echantillon);
  mono_add_internal_call("Prologin.Api::Transmuter", (const void*)transmuter);
  mono_add_internal_call("Prologin.Api::Catalyser", (const void*)catalyser);
  mono_add_internal_call("Prologin.Api::DonnerEchantillon", (const void*)donner_echantillon);
  mono_add_internal_call("Prologin.Api::TypeCase", (const void*)type_case);
  mono_add_internal_call("Prologin.Api::EstVide", (const void*)est_vide);
  mono_add_internal_call("Prologin.Api::ProprieteCase", (const void*)propriete_case);
  mono_add_internal_call("Prologin.Api::ProprieteCaseType", (const void*)propriete_case_type);
  mono_add_internal_call("Prologin.Api::TailleRegion", (const void*)taille_region);
  mono_add_internal_call("Prologin.Api::PositionsRegion", (const void*)positions_region);
  mono_add_internal_call("Prologin.Api::PlacementPossibleEchantillon", (const void*)placement_possible_echantillon);
  mono_add_internal_call("Prologin.Api::PlacementsPossibleEchantillon", (const void*)placements_possible_echantillon);
  mono_add_internal_call("Prologin.Api::Historique", (const void*)historique);
  mono_add_internal_call("Prologin.Api::Moi", (const void*)moi);
  mono_add_internal_call("Prologin.Api::Adversaire", (const void*)adversaire);
  mono_add_internal_call("Prologin.Api::Score", (const void*)score);
  mono_add_internal_call("Prologin.Api::TourActuel", (const void*)tour_actuel);
  mono_add_internal_call("Prologin.Api::Annuler", (const void*)annuler);
  mono_add_internal_call("Prologin.Api::NombreCatalyseurs", (const void*)nombre_catalyseurs);
  mono_add_internal_call("Prologin.Api::EchantillonTour", (const void*)echantillon_tour);
  mono_add_internal_call("Prologin.Api::APoseEchantillon", (const void*)a_pose_echantillon);
  mono_add_internal_call("Prologin.Api::ADonneEchantillon", (const void*)a_donne_echantillon);
  mono_add_internal_call("Prologin.Api::QuantiteTransmutationOr", (const void*)quantite_transmutation_or);
  mono_add_internal_call("Prologin.Api::QuantiteTransmutationCatalyseur", (const void*)quantite_transmutation_catalyseur);
  mono_add_internal_call("Prologin.Api::QuantiteTransmutationCatalyseurOr", (const void*)quantite_transmutation_catalyseur_or);
  mono_add_internal_call("Prologin.Api::EchantillonDefautPremierTour", (const void*)echantillon_defaut_premier_tour);
  mono_add_internal_call("Prologin.Api::AfficherEtablis", (const void*)afficher_etablis);
  mono_add_internal_call("Prologin.Api::AfficherCaseType", (const void*)afficher_case_type);
  mono_add_internal_call("Prologin.Api::AfficherElementPropriete", (const void*)afficher_element_propriete);
  mono_add_internal_call("Prologin.Api::AfficherErreur", (const void*)afficher_erreur);
  mono_add_internal_call("Prologin.Api::AfficherActionType", (const void*)afficher_action_type);
  mono_add_internal_call("Prologin.Api::AfficherPosition", (const void*)afficher_position);
  mono_add_internal_call("Prologin.Api::AfficherEchantillon", (const void*)afficher_echantillon);
  mono_add_internal_call("Prologin.Api::AfficherPositionEchantillon", (const void*)afficher_position_echantillon);
  mono_add_internal_call("Prologin.Api::AfficherActionHist", (const void*)afficher_action_hist);
}

MonoImage* CSharpInterface::getImage()
{
    return _image;
}

MonoDomain* CSharpInterface::getDomain()
{
    return _domain;
}

CSharpInterface::~CSharpInterface()
{
  mono_image_close(_image);
  mono_assembly_close(_assembly);
  // XXX -- mono segfaults when calling this. Seems to be a known bug
  //        appearing when mono_jit_clean() is called from a dtor. ???
  //mono_jit_cleanup(_domain);
}

/*
** Calls C# functions from C++
*/
MonoObject* CSharpInterface::callCSharpMethod(const char* name)
{
  MonoThread*   thread = mono_thread_attach(_domain);
  MonoMethod*   method = mono_class_get_method_from_name(_class, name, 0);
  MonoObject*   object = mono_runtime_invoke(method, _object, NULL, NULL);

  mono_thread_detach(thread);

  return object;
}

/*
** Functions called from stechec to C.
*/
void partie_init()
{
  gl_csharp.callCSharpMethod("PartieInit");
}
void jouer_tour()
{
  gl_csharp.callCSharpMethod("JouerTour");
}
void partie_fin()
{
  gl_csharp.callCSharpMethod("PartieFin");
}
