dll — GetProcAddress для импорта украшенной функции C ++ в переполнение стека

В Visual C ++ 2013 я пытаюсь экспортировать функцию из проекта «плагина»:

void registerFactories(FactoryRegister<BaseShape> & factoryRegister);

Которая компилируется в динамическую dll, которая будет связана во время выполнения с помощью проекта приложения. Сначала я определяю тип указателя на функцию:

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

Который используется как:

        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;
}

Тем не менее GetProcAddress возвращает NULL.

Я могу подтвердить, что я могу экспортировать функции C (используя extern "C") и импортировать их из одной и той же DLL, используя GetProcAddress, но я не могу импортировать функцию C ++. например это работает:

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

затем

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

Так что я предполагаю, что мне нужно как-то рассмотреть искаженное имя, которое экспортируется для registerFactories, Поскольку он должен иметь дело с типами C ++, в идеале я хочу сделать это без export "C",

Вот что dumpbin.exe видит:

Дамп файла examplePlugin.dll

Тип файла: 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

РЕДАКТИРОВАТЬ :

registerFactories это не имя, чтобы дать GetProcAddress, Путем ручного копирования искаженного имени из bindump, например:

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

Оно работает! Поэтому многие из ответов ниже связаны с обнаружением этого искаженного имени во время выполнения.

2

Решение

Я бы не стал охотиться за искалеченным именем. Это зависит от компилятора (что означает, также зависит от версии), и даже если это работает, это будет хрупкое решение.

Я бы посоветовал получить адрес вашего RegisterFactoriesType другим способом.

Предполагая, что в вашем плагине есть функция инициализации C-Style (адрес которой доступен через GetProcAddress), я бы сделал это:

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

затем внутри init (так внутри DLL)

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

По сути, вы просите DLL дать вам адрес фабричной функции. Код dll не нуждается в GetProcAddr, он может использовать адрес (&)

3

Другие решения

я создал библиотека специально для этого некоторое время назад.
Есть пример использования Вот что я надеюсь поможет.

1

По вопросам рекламы [email protected]