I would do like the system linker does: construct a symbol table containing all the function names. Then just initialise the pointers in that table. Function names can either be fixed string constants, or they might be read from the DLL itself (i.e. Win32 API to enumerate dll export functions?).
Significant drawback of that table approach, though, is impossibility to use it with existing code, which calls the functions by name (pPy_Initialize();
) -- you'd have to use the pointer in the table, perhaps indexed via enum (pPy[Initialize]();
).
Different signatures can be handled by using different tables (a table per signature). Signatures can also be stored along with the names in some symbolic form, and then you'd wrap it in some accessor magic which could parse and check it -- but that could quickly become too complex, like inventing yet another programming language.
IMHO, the only significant advantage of all that weird machinery over macros is that you might be able to load arbitrary DLLs with it. Other than that, I wouldn't go that route.