This is a school thing.
Here’s the problem:
We’re working on a Bomberman clone, and we have to implement a scripting interface, allowing the user to make his own “artificial intelligence”.
We chose to use Perl. Right now, I build the perl module like this:
Here are the files (test purpose):
SaibApi.xs:
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
#include "ppport.h"
#include "SaibApi.hpp"
MODULE = SaibApi PACKAGE = SaibApi
SaibApi *
SaibApi::new()
void
SaibApi::DESTROY()
void
SaibApi::PrintLol()
void
SaibApi::PrintPvar()
void
SaibApi::setLol(int arg)
SaibApi.hpp
#ifndef SAIBAPI_HPP_
# define SAIBAPI_HPP_
#include <iostream>
class SaibApi {
public:
SaibApi() {}
~SaibApi() {}
void PrintLol() { std::cout << "loln"; }
void PrintPvar() { std::cout << _lol << "n"; }
void setLol(int arg) {_lol = arg;}
private:
int _lol;
};
#endif /* !SAIBAPI_HPP_ */
Makefike.PL:
use 5.014002;
use ExtUtils::MakeMaker;
my $CC = 'g++';
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
NAME => 'SaibApi',
VERSION_FROM => 'lib/SaibApi.pm', # finds $VERSION
PREREQ_PM => {}, # e.g., Module::Name => 1.1
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'lib/SaibApi.pm', # retrieve abstract from module
AUTHOR => 'Arkeopix <arkeopix@>') : ()),
LIBS => [''], # e.g., '-lm'
DEFINE => '', # e.g., '-DHAVE_SOMETHING'
INC => '-I.', # e.g., '-I. -I/usr/include/other'
# Un-comment this if you add C files to link with later:
# OBJECT => '$(O_FILES)', # link all the C files too
CC => $CC,
LD => '$(CC)',
XSOPT => '-C++',
TYPEMAPS => ['perlobject.map'],
);
For clarity purpose, i excluded typemaps files.
The module is correctly built and i’m able to instantiate the SaibApi class in perl.
Now our problem is that there is apparently no way to instantiate the class in c++ and in perl at the same time. What we’re trying to do is to give the user a simple API, allowing to get objects from our C++ code (lots of std::list containing maps, players etc…) via simple methods.
eg:
#! /usr/bin/perl -w
#use SaibApi;
my $ai = new SaibApi();
my @map = ai->GetMap();
# some more code here...
We’ve made a lot of research but the documentation about XS is a bit scarce. We’re stuck right now. How one would instantiate the class in c++ and in perl at the same time, allowing to set _lol
in the c++ part and print it in the perl part without having to use the SetLol()
method ? And if not possible, what are the alternatives ?
2
Answers
In the end we decided to go with shared memory, for the deadline approaches really fast.
First we create the memory segment with
shmget()
, share our data withshmat()
and then push the content of our lists on the script stack withXPUSHs()
.Maybe it's no the prettiest way to do this, but it works rather well.
I’d recommend using ExtUtils::XSpp and Module::Build::WithXSpp. they make interfacing with C++ much easier.