summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dyer <cdyer@cab.ark.cs.cmu.edu>2012-10-11 21:57:18 -0400
committerChris Dyer <cdyer@cab.ark.cs.cmu.edu>2012-10-11 21:57:18 -0400
commit64f5a686dbfb128b7dfce1d6d842ba976da8c22f (patch)
tree6c81fe8b366f3ad84f38e8e075beb965bf04a722
parent07ea7b64b6f85e5798a8068453ed9fd2b97396db (diff)
add support for dlopen'd feature functions
-rw-r--r--configure.ac3
-rw-r--r--decoder/Makefile.am1
-rw-r--r--decoder/cdec_ff.cc2
-rw-r--r--decoder/ff.h1
-rw-r--r--decoder/ff_external.cc57
-rw-r--r--decoder/ff_external.h26
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