2

In Visual C++ 2013, I'm trying to export a function from a 'plugin' project:

void registerFactories(FactoryRegister<BaseShape> & factoryRegister);

Which is compliled into a dynamic dll which will be linked at runtime by an 'application' project. First I define the function pointer type:

    typedef void (*RegisterFactoriesType)(FactoryRegister<BaseShape> &);

Which is used as:

        auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "registerFactories");
        if (!registerFactories) {
            if (verbose) {
                ofLogWarning("ofxPlugin") << "No factories for FactoryRegister<" << typeid(ModuleBaseType).name() << "> found in DLL " << path;
            }
            FreeLibrary(dll);
            return false;
        }

However, the GetProcAddress returns NULL.

I can confirm that I can export C functions (using extern "C") and import them from the same DLL using GetProcAddress, but I importing the C++ function fails. e.g. this works:

extern "C" {
    OFXPLUGIN_EXPORT void testFunction(int shout);
}

then

auto testFunction = (TestFunction)GetProcAddress(dll, "testFunction");
if (testFunction) {
    testFunction(5);
}

So my presumption is that I need to somehow consider the mangled name which is exported for registerFactories. Since it needs to deal with C++ types, ideally I want to do this without export "C".

Here's what dumpbin.exe sees:

Dump of file examplePlugin.dll

File Type: DLL

Section contains the following exports for examplePlugin.dll

  00000000 characteristics
  558A441E time date stamp Wed Jun 24 14:46:06 2015
      0.00 version
         1 ordinal base
         2 number of functions
         2 number of names

  ordinal hint RVA      name

        1    0 001B54E0 ?registerFactories@@YAXAEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z = ?registerFactories@@YAXAEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z (void __cdecl registerFactories(class ofxPlugin::FactoryRegister<class BaseShape> &))
        2    1 001B5520 testFunction = testFunction

Summary

     86000 .data
     8E000 .pdata
    220000 .rdata
      E000 .reloc
      1000 .rsrc
    65D000 .text

EDIT :

registerFactories is not the name to give to GetProcAddress. By manually copying the mangled name from bindump e.g.:

        auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "?registerFactories@@YAXPEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z");

It works! Therefore many of the answers below are related to discovering this mangled name at runtime.

Elliot Woods
  • 834
  • 11
  • 20
  • What stopped you from querying the mangled name (or asking a question; either one)? – WhozCraig Jun 24 '15 at 06:14
  • Well, you know that "registerFactories" is wrong. You have to use the mangled name. – Hans Passant Jun 24 '15 at 06:42
  • I'm not going to close this as a duplicate of [this](http://stackoverflow.com/questions/16016732/is-there-a-way-to-find-the-c-mangled-name-to-use-in-getprocaddress) since I wrote that question, but they're at least related. – MSalters Jun 24 '15 at 08:00
  • Yes that's a good reference. I guess the answer to mine is 'you need to use mangled names' and the question of yours is 'how do you use mangled names?' – Elliot Woods Jun 24 '15 at 10:08

2 Answers2

3

I would not start a hunt for the mangled name. It's compiler dependent (which means also version dependent) and even if it works it would be a fragile solution.

I would suggest to get the address of your RegisterFactoriesType in antother way.

Assuming you have, in your plugin, a C-Style init function (whose address is available via GetProcAddress) I would do this:

struct init_data_t
{
   RegisterFactoriesType  factory ;
   ... other members
} ;

then inside init (so inside the DLL)

void init(init_data_t *data)
{
    init_data->factory = &dll_factory ;
}

Basically you ask the DLL to give you the address of the factory function. The dll code does not need GetProcAddr, it can use address of (&)

marom
  • 5,064
  • 10
  • 14
1

I created a library specifically for this purpose some time ago. There is a usage example here that I hope will help.

user1233963
  • 1,450
  • 15
  • 41
  • Thanks for this! Very nice solution. Considering if the other answer gives a clean solution without any extra libraries before marking an answer. – Elliot Woods Jun 24 '15 at 06:57