6

I was thinking it would be cool to have a few classes to wrap around LoadLibrary and GetProcAddress, Library and Function respectively. As I was thinking about this I'm not sure its possible. Here is what I'm thinking:

Library class:

class Library
{
    HANDLE m_handle;
public:
    // Handles initializing the DLL:
    Library(std::string name);
    // Deinitializes the DLL
    ~Library();

    HANDLE getHandle();
    bool isInitialized();
}

And the Function class:

class Function
{
public:
    Function(Library& library, std::string name);


    void* call(/* varg arguments? */) throw(exception);

    bool isValid();
}

Problem arises because I have to have dynamic data types for the parameters and multiple lengths to pass to the real function pointer. I could get around the multiple lengths of the arguments by specifying it in the constructor and have specific methods but what about the data types?

EDIT: I've created classes based on the answers for anyone to use here: https://github.com/ic3man5/ice--

David
  • 692
  • 8
  • 21
  • If you are using C++11, you could go with a variadic template. – Björn Pollex Nov 04 '11 at 07:19
  • 1
    The function type is always statically known, otherwise it wouldn't be callable from regular C++ code. Make the function signature a template argument. – K-ballo Nov 04 '11 at 07:20
  • 2
    I can understand wrapping a HMODULE handle (though I'd just stick it in a `shared_ptr` with a proper destructor functor), but why do you need to wrap the functions? You have to know what the signature is for a function beforehand. So you may as well just perform the cast and stick it in a variable. If it makes you feel more C++-ish, you can stick it in a std/boost::function object instead of a regular function pointer. But the function pointers don't have to be cleaned up, so you gain nothing by using an object to wrap them. – Nicol Bolas Nov 04 '11 at 07:24
  • see http://stackoverflow.com/q/1854323/79455 it looks like you are trying to make something like http://boost-extension.redshoelace.com/docs/boost/extension/index.html – rve Nov 04 '11 at 07:35
  • I second Nicol's opinion. You can find methods to solve problem but do we really need to solve it? the signature and function prototype is know before hand. then getting the void* function pointer and calling it with required parameter can be done outside. You can save lot of time on packing data and making it complex methods to identify the types. – sarat Nov 04 '11 at 07:39
  • Use [Poco::ClassLoader](http://pocoproject.org/docs/Poco.ClassLoader.html) – ali_bahoo Nov 04 '11 at 07:42
  • @NicolBolas, I'd like something 'clean' to work with while keeping the code as simple as possible. See my response to avakar's answer below for details. – David Nov 09 '11 at 01:58
  • @DavidRebbe: And what is not "clean" about having a function pointer? It's statically typed, since you have to name the type of the function. The only un"clean" part of function pointers is doing the cast from a `void*` that you get from GetProcAddress. And that you only have to do at load time. And even then, how many pointers are you planning on loading? – Nicol Bolas Nov 09 '11 at 02:07
  • @NicolBolas, Roughly about 20-30 function pointers all with variable parameters (comparing each function) and types at the moment but it would be awesome to make it flexible enough to use in other projects I do. I just thought it would be cool to be able to what avakar showed below but making it dynamic; Would something like that be possible with variadic templates? I don't mind using c++11 features now that the standard is finalized. EDIT: I just realized Bjorn Pollex mentioned using variadic templates above... – David Nov 09 '11 at 05:14
  • @DavidRebbe: Like I said below, C++ is a statically typed language. Variadic templates won't help, because you still need a way to _verify_ that the types you're using to call the object are the types that the function pointer expects. And since `GetProcAddress` returns a `void*`, that information does not exist. _You_ must provide it. So, for a particular library, you must _know_ what the signature of each you get function is. Otherwise, your "clean" variadic functor is very unsafe, since you could call it with anything, and it will happily do a cast and break in unpredictable ways. – Nicol Bolas Nov 09 '11 at 05:32

2 Answers2

9

You can implement implicit conversion to a function pointer.

template <typename Signature>
struct Function
{
    Function(Library& library, std::string name)
    {
        m_func = reinterpret_cast<Signature *>(
            ::GetProcAddress(library.m_hModule, name.c_str()));
    }
    operator Signature *() { return m_func; }
private:
    Signature * m_func;
};

Use the class as follows:

Function<int (int, double)> foo(library, "foo");
int i = foo(42, 2.0);
avakar
  • 32,009
  • 9
  • 68
  • 103
  • This actually looks close to what I want. But I'm assuming you need to know the number of parameters ahead of time in `operator Signature *() { /*...*/ }`. That way I could use the class `Function` with any "library" functions without having to rewrite the class. This is beneficial to me as I can check reoccurring parameters for a library for certain conditions. Python you'd be able to pass a `tuple` and expand it with * as parameters. – David Nov 09 '11 at 01:51
  • @DavidRebbe: Python is not a statically typed language, so it can get away with gimmicks like that. C++ cannot. At all times, C++ must know, at compile time, what everything is. So you can't just "call stuff"; you have to provide an actual signature. – Nicol Bolas Nov 09 '11 at 02:04
  • @DavidRebbe, I'm not sure what you mean -- you don't need to know the number of parameters to write the `Function` template. I've added concrete implementation for you, it should make things clearer. – avakar Nov 09 '11 at 07:55
  • @avakar, Thanks for the rewrite above. I think I almost have it, Could you be kind enough to explain `` syntax or point me to an article that explains this? My knowledge in templates are kind of weak. I'm going to be posting my code on github (or similar) once I get a working example. – David Nov 10 '11 at 04:21
1

You could look into Qt's QPluginLoader & QLibrary for inspiration.

Regarding calling dynamically loaded functions with arbitrary signature, you could use LibFFI

All this is from a Linux point of view, I don't know Windows and I don't know the equivalent there (but both Qt & LibFFI are ported to Windows)

Notice that calling an arbitrary function thru a pointer can be compiler, processor and ABI specific (hence libFFI contains non-portable code).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • LibFFI looks like an interesting project, I might have to end up using this. But if not, I'll keep it in my back pocket. – David Nov 09 '11 at 02:01