tags:

views:

86

answers:

4

I'm wondering if anyone knows how to accomplish the following:

Let's say I have a bunch of data stored in SQL, lets say one of the fields could be called funcName, function name would contain data similar to "myFunction" What I'm wondering is, is there a way I can than in turn extract the function name and actually call that function?

There's a few ways I can think of to accomplish this, one is changing funcName to funcId and linking up with an array or similar, but I'm looking for something a bit more dynamic that would allow me to add the data on fly without having to update the actual source code every time I add a call to a new function assuming of course that the function already exists and is accessible via scope location we call it from.

Any help would be greatly appreciated.

+1  A: 

You can use the text you recevied from SQL and call GetProcAddress()

this will give you a function pointer you can call (assuming you are using Windows).

For Linux, take a look at dlsym

Kevin
Correct me if I'm wrong, but it appears GetProcAddress() refers to exported functions/variables in DLL's, my current program does not export anything to DLL.
Undawned
@Undawned Then you'll have to make dll that exports all functions you want to use.
SigTerm
You can export functions from an .EXE as well, no DLL needed.
Ben Voigt
@Ben: that's not supported for `GetProcAddress`; documentation says DLL only.
MSalters
@MSalters: If the EXE has an export table, it will work.
Kevin
It *may* work. Today. That's why I said that it's not _supported_, and point to the documentation. And once a virus abuses it, the undocumented route _will_ be closed down.
MSalters
+2  A: 

Setup a mapping of names to function pointers or functors at program startup, then call by name via map lookup. Can also use dynamic libraries for extensions.

In the compiler/interpreter world it's called a symbol table, which usually also holds type (classes/structs), data declarations (variables), and function descriptors (argument and return types, etc.) It can also be nested according to the scope.

Nikolai N Fetissov
+1  A: 

Approach #1 (most complicated):
Develop plugin system consisting of several dynamically linked libraries (*.dll on win, *.so on linux), with a few public functions that will tell your application which this plugin supports, function names, and pointers. Scan for plugins on startup, build function list that will map function names to their pointers.

Expect problems with variable number of parameters.

Approach #2 (brute force): Store all functions that you should be able to call within one dynamically linked library. When function name is extracted from database, get function pointer using GetProcAddress (win32) or dlsym(?) on linux.

Expect problems with variable number of parameters. Not the fastest, and not a smartest way.

Approach #3 (most flexible): Embed lua or python interpreter in your app.
This way you'll be able to store entire functions within database and should not have problems calling one of those. You'll still have to declare list of function you'll want to be accessable.

This won't be fool/hack proof, though, it will be possible to screw up entire app from within database, if you aren't careful enough.

SigTerm
Good reply, unfortunately the methods suggested require a bit too much overhauling on the overall project itself while what I'm working on is a smaller portion of the project that doesn't justify such a large overhaul on the base code. Thanks for the information though =).
Undawned
+3  A: 

Use a macro to define new functions that register themselves automatically.

// callable_function.h
class CallableFunction {
 public:
  virtual void operator()() = 0;
};

class CallableFunctionRegistry {
 public:
  static CallableFunction *Register(const string &func_name,
                                    CallableFunction *func_impl) {
    Instance()->registered_functions_.insert(make_pair(func_name, func_impl));
  }

  static void Run(const string &func_name) {
    (*Instance()->registered_functions_[func_name])();
  }

 private:
  static CallableFunctionRegistry *Instance() {
    static CallableFunctionRegistry *instance = new CallablefunctionRegistry;
    return instance;
  }

  CallableFunctionRegistry() {}
  map<string, CallableFunction*> registered_functions_;
};

#define REGISTER_CALLABLE_FUNCTION(FuncName) \
  class FuncName : public CallableFunction { \
   public: \
    virtual void operator()(); \
  }; \
  CallableFunction *impl_ ##FuncName = \
    CallableFunctionRegistry::Register(#FuncName, new FuncName); \
  void FuncName::operator()()

And use it like this:

//other_file.cc
REGISTER_CALLABLE_FUNCTION(DoStuff) {
  // do stuff here.
}

And this:

//yet_another_file.cc
CallableFunctionRegistry::Run("DoStuff");

You could do it with function ptrs instead of CallableFunction object, but my syntax on that is hazy. Either way, add error checking for duplicate registrations and lookup not found.

Stephen
Wow, while I might not be using this code exactly it did lead me to another avenue that I'm going to try a bit later to accomplish my goal. Thank you very much for the reply and information =).
Undawned
Good luck, glad I could help.
Stephen