diff options
author | Chris Dyer <cdyer@cab.ark.cs.cmu.edu> | 2012-10-11 21:57:18 -0400 |
---|---|---|
committer | Chris Dyer <cdyer@cab.ark.cs.cmu.edu> | 2012-10-11 21:57:18 -0400 |
commit | fc13e7db2af155a7b636e4061f3567ea3957fd9a (patch) | |
tree | 072eb2915118a8abd4ae7b26fbec44f07ca59764 | |
parent | 9339c80d465545aec5a6dccfef7c83ca715bf11f (diff) |
add support for dlopen'd feature functions
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | decoder/Makefile.am | 1 | ||||
-rw-r--r-- | decoder/cdec_ff.cc | 2 | ||||
-rw-r--r-- | decoder/ff.h | 1 | ||||
-rw-r--r-- | decoder/ff_external.cc | 57 | ||||
-rw-r--r-- | decoder/ff_external.h | 26 |
6 files changed, 89 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 70e8e932..967b657c 100644 --- a/configure.ac +++ b/configure.ac @@ -14,7 +14,8 @@ BOOST_REQUIRE([1.44]) BOOST_PROGRAM_OPTIONS BOOST_TEST AM_PATH_PYTHON -# TODO detect Cython, generate python/Makefile that calls "python setup.py build" +AC_CHECK_HEADER(dlfcn.h,AC_DEFINE(HAVE_DLFCN_H)) +AC_CHECK_LIB(dl, dlopen) AC_ARG_ENABLE(mpi, [ --enable-mpi Build MPI binaries, assumes mpi.h is present ], diff --git a/decoder/Makefile.am b/decoder/Makefile.am index 4a98a4f1..28863dbe 100644 --- a/decoder/Makefile.am +++ b/decoder/Makefile.am @@ -33,6 +33,7 @@ libcdec_a_SOURCES = \ cfg.cc \ dwarf.cc \ ff_dwarf.cc \ + ff_external.cc \ rule_lexer.cc \ fst_translator.cc \ csplit.cc \ diff --git a/decoder/cdec_ff.cc b/decoder/cdec_ff.cc index b516c386..54f6e12b 100644 --- a/decoder/cdec_ff.cc +++ b/decoder/cdec_ff.cc @@ -18,6 +18,7 @@ #include "ff_charset.h" #include "ff_wordset.h" #include "ff_dwarf.h" +#include "ff_external.h" #ifdef HAVE_GLC #include <cdec/ff_glc.h> @@ -69,6 +70,7 @@ void register_feature_functions() { ff_registry.Register("WordPairFeatures", new FFFactory<WordPairFeatures>); ff_registry.Register("WordSet", new FFFactory<WordSet>); ff_registry.Register("Dwarf", new FFFactory<Dwarf>); + ff_registry.Register("External", new FFFactory<ExternalFeature>); #ifdef HAVE_GLC ff_registry.Register("ContextCRF", new FFFactory<Model1Features>); #endif diff --git a/decoder/ff.h b/decoder/ff.h index 6c22d39f..227787ca 100644 --- a/decoder/ff.h +++ b/decoder/ff.h @@ -27,6 +27,7 @@ typedef std::vector<WordID> Features; // set of features ids // depends on context, you may also need to implement // FinalTraversalFeatures(...) class FeatureFunction { + friend class ExternalFeature; public: std::string name_; // set by FF factory using usage() bool debug_; // also set by FF factory checking param for immediate initial "debug" diff --git a/decoder/ff_external.cc b/decoder/ff_external.cc new file mode 100644 index 00000000..520e98b1 --- /dev/null +++ b/decoder/ff_external.cc @@ -0,0 +1,57 @@ +#include "ff_external.h" +#include "stringlib.h" + +#include <dlfcn.h> + +using namespace std; + +ExternalFeature::ExternalFeature(const string& param) { + size_t pos = param.find(' '); + string nparam; + string file = param; + if (pos < param.size()) { + nparam = Trim(param.substr(pos + 1)); + file = param.substr(0, pos); + } + if (file.size() < 1) { + cerr << "External requires a path to a dynamic library!\n"; + abort(); + } + lib_handle = dlopen(file.c_str(), RTLD_LAZY); + if (!lib_handle) { + cerr << "dlopen reports: " << dlerror() << endl; + cerr << "Did you provide a full path to the dynamic library?\n"; + abort(); + } + FeatureFunction* (*fn)(const string&) = + (FeatureFunction* (*)(const string&))(dlsym(lib_handle, "create_ff")); + if (!fn) { + cerr << "dlsym reports: " << dlerror() << endl; + abort(); + } + ff_ext = (*fn)(nparam); +} + +ExternalFeature::~ExternalFeature() { + delete ff_ext; + dlclose(lib_handle); +} + +void ExternalFeature::PrepareForInput(const SentenceMetadata& smeta) { + ff_ext->PrepareForInput(smeta); +} + +void ExternalFeature::FinalTraversalFeatures(const void* context, + SparseVector<double>* features) const { + ff_ext->FinalTraversalFeatures(context, features); +} + +void ExternalFeature::TraversalFeaturesImpl(const SentenceMetadata& smeta, + const Hypergraph::Edge& edge, + const std::vector<const void*>& ant_contexts, + FeatureVector* features, + FeatureVector* estimated_features, + void* context) const { + ff_ext->TraversalFeaturesImpl(smeta, edge, ant_contexts, features, estimated_features, context); +} + diff --git a/decoder/ff_external.h b/decoder/ff_external.h new file mode 100644 index 00000000..283e58e8 --- /dev/null +++ b/decoder/ff_external.h @@ -0,0 +1,26 @@ +#ifndef _FFEXTERNAL_H_ +#define _FFEXTERNAL_H_ + +#include "ff.h" + +// dynamically loaded feature function +class ExternalFeature : public FeatureFunction { + public: + ExternalFeature(const std::string& param); + ~ExternalFeature(); + virtual void PrepareForInput(const SentenceMetadata& smeta); + virtual void FinalTraversalFeatures(const void* context, + SparseVector<double>* features) const; + protected: + virtual void TraversalFeaturesImpl(const SentenceMetadata& smeta, + const Hypergraph::Edge& edge, + const std::vector<const void*>& ant_contexts, + FeatureVector* features, + FeatureVector* estimated_features, + void* context) const; + private: + void* lib_handle; + FeatureFunction* ff_ext; +}; + +#endif |