v01d has asked for the wisdom of the Perl Monks concerning the following question:
Hi, I've been trying to create an extension to be able to use my libaiml library (c++) from within perl. I tried swig, but the class I define in the main header of the library is inside a namespace and swig doesn't support them.
Well, I tried xs afterwards and I quickly got a module that looked it was going to work. I managed to expose the constructor, destructor and 3 other functions. But I don't know how to expose the most important function.
This function takes 2 const std::string& and 1 std::string& where I put my output. The function returns a boolean, indicating success or failure.
What I don't know how to do is how to create a Perl interface for that. I can think of two versions: return a scalar (which would be undef if the function returns false, otherwise it would contain the value written to the third parameter (in C++)). The other version is the closest one to C++: return a scalar (a boolean), take 2 scalars by copy and the last one by reference.
Now... how do I do this? I would like to come up with a C++ solution by writing C++ code, and not fiddling so much with the code below the "MODULE" line on the .xs file.
So, my current xs file is this one:
#ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #ifdef __cplusplus } #endif #include <string> #include <libaiml/core.h> using std::string; using aiml::cCore; using aiml::AIMLError; class cAiml : public cCore { public: // Here I could write a function which would call respond() // but doing things more Perl Friendly }; MODULE = AI::AIML PACKAGE = AI::AIML cAiml * cAiml::new() void cAiml::DESTROY() bool cAiml::initialize(const char* file) void cAiml::deinitialize() long cAiml::get_error() const char* cAiml::get_error_str(AIMLError error_num);
my typemap:
TYPEMAP cAiml * O_OBJECT AIMLError T_ENUM
the main header of my library:
/********************************************************************* +****** * This file is part of "libaiml" + * * Copyright (C) 2005 by V01D + * * + * * "libaiml" is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published + by * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * * + * * "libaiml" is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with "libaiml"; if not, write to the + * * Free Software Foundation, Inc., + * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ********************************************************************* +******/ #ifndef __LIBAIML_CORE_H__ #define __LIBAIML_CORE_H__ #define LIBAIML_MAX_LINE_SIZE 16384 // max size a +line of text can be (doesn't apply to .aiml files) #define LIBAIML_POPEN_BUFFER_SIZE 256 + // buffer size used when reading data from popen() #define LIBAIML_VERSION_STRING ("libaiml 0.4") #define LIBAIML_VERSION (0.4) #include <string> #include <fstream> #include <vector> #include <list> #include <map> #include <std_utils/cconfig.h> #include "global.h" #include "errors.h" #include "aiml_parser.h" namespace _aiml { class cCore { public: cCore(void); ~cCore(void); bool initialize(const std::string& file); void deinitialize(void); bool respond(const std::string& input, const std::string& username +, std::string& output); void unregister_user(const std::string& user_id); AIMLError get_error(void); const char* get_error_str(AIMLError error_num); private: friend class cGraphMaster; /** Error handling **/ AIMLError last_error; static const char* error_str[AIMLERR_MAX]; void set_error(AIMLError); /** Utility Functions **/ bool load_substitutions(void); bool load_botvars(void); void load_aiml_files(void); void learn_file(const std::string& filename, bool at_runtime = fal +se); bool load_userlist(void); void save_userlist(void); std::string doSystemCall(const std::string& cmd); std::string doJavaScriptCall(const std::string& cmd); /** ADD: implement this **/ bool load_defvars(void); const std::string& getBotVar(const std::string& key) const; StringMAP botvars_map; /** Internal modules **/ cGraphMaster graphmaster; AIMLparser aiml_parser; /** Configuration options/vars **/ std_util::cConfig cfg; std::ofstream file_gossip_stream; std::string aiml_path, file_substitute, file_gossip, file_botvars, + aiml_files, user_dir; bool should_trim_blanks, allow_system; /** User management **/ typedef std::map<std::string,_aiml::cUser> UserMap; typedef std::list<UserID> UserIDS; UserMap user_map; UserIDS user_ids; bool get_free_uid(UserID* ptr); }; } /** * Public Interface */ namespace aiml { using _aiml::cCore; using _aiml::AIMLError; } #endif // __LIBAIML_CORE_H__
It works pretty well like this, just that I can't use respond() with that .xs.
Any help apreciated, I've been googling and reading and man'ning a lot, and can't find anything that clears this for me.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: C++ strings, references and XS (char*)
by tye (Sage) on Dec 20, 2005 at 07:44 UTC | |
by v01d (Novice) on Dec 20, 2005 at 16:08 UTC | |
by tye (Sage) on Dec 20, 2005 at 16:31 UTC | |
by v01d (Novice) on Dec 20, 2005 at 21:58 UTC | |
|
Re: C++ strings, references and XS
by reneeb (Chaplain) on Dec 20, 2005 at 02:42 UTC | |
by v01d (Novice) on Dec 20, 2005 at 02:59 UTC |