// Example of calling C++ code from SICStus
// Last updated for 3.9.0
// sicstus-support@sics.se

#include <windows.h>
#include <stdio.h>
#include "cplus.h"
#include "cplus_glue.h"         // generated by splfr from the foreign/2 declarations in cplus.pl

long CPPTest::get_i(void)
{
  return ivar;
}

void CPPTest::set_i(long i)
{
  ivar = i;
}

SP_term_ref CPPTest::get_t(void)
{
  SP_term_ref t = SP_new_term_ref();

  SP_put_integer(t, ivar);
  return t;
}

void CPPTest::set_t(SP_term_ref t)
{
  SP_get_integer(t, &ivar);
}

//-------------------------------------------------------------------

// . All procedures accessed through foreign declarations must have
//   extern "C" linkage.
// . Note that we map pointers onto the foreign resource type
//   'integer' (that is, C/C++ long) instead of 'address'. The reason
//   is that the 'address' type only is guaranteed to work for pointers 
//   allocated with the SICStus memory allocation routines (SP_malloc
//   et al.). If sizeof (long) < sizeof (void*) then we are in trouble 
//   but that should not be an issue on any platform supported by
//   SICStus.


extern "C" long SPCDECL cpptest_create(void)
{
  return (long) new CPPTest;
}

extern "C" long SPCDECL cpptest_get_i(long x)
{
  CPPTest *obj = (CPPTest *)x;
  return obj->get_i();
}

extern "C" void SPCDECL cpptest_set_i(long x, long i)
{
  CPPTest *obj = (CPPTest *)x;
  obj->set_i(i);
}

extern "C" SP_term_ref SPCDECL cpptest_get_t(long x)
{
  CPPTest *obj = (CPPTest *)x;
  return obj->get_t();
}

extern "C" void SPCDECL cpptest_set_t(long x, SP_term_ref t)
{
  CPPTest *obj = (CPPTest *)x;
  obj->set_t(t);
}

//-------------------------------------------------------------------

CPPTest stat_obj;

extern "C" long SPCDECL cpptest_stat_obj(void)
{
  fprintf(stderr, "&stat_obj == 0x%lx\n", (unsigned long)&stat_obj);

  return (long) &stat_obj;
}

