2012-01-15 2 views
1

Я пытаюсь сделать небольшой тестовый плагин, используя NPAPI для firefox. Это мой код до сих пор:Почему экспортированные функции неправильно названы в DLL?

/* File: npp_test.cpp 
    Copyright (c) 2012 by Niklas Rosenstein 

    Testing the NPAPI interface. */ 

// - Includes & Preprocessors -------------------------------------------------- 
// - -------- - ------------- -------------------------------------------------- 

#define DEBUG 

#ifdef DEBUG 
# include <iostream> 
    using namespace std; 
# include <windows.h> 
#endif // DEBUG 

#include <stdint.h> 

#include <npapi.h> 
#include <npfunctions.h> 
#include <npruntime.h> 

#define DLLEXPORT extern __declspec(dllexport) 

// - NPAPI Calls --------------------------------------------------------------- 
// - ----- ----- --------------------------------------------------------------- 

NPError NP_New(NPMIMEType pluginType, NPP npp, uint16_t mode, int16_t argc, 
       char* argn[], char* argv[], NPSavedData* saved); 

// - Entrypoints ---------------------- 
// - ----------- ---------------------- 

NPError NP_GetEntryPoints(NPPluginFuncs* pFuncs) { 
# ifdef DEBUG 
    cout << "NP_GetEntryPoints\n"; 
# endif // DEBUG 

    // Initialize plugin-functions 
    pFuncs->newp = NP_New; 

    return NPERR_NO_ERROR; 
} 

NPError NP_Initialize(NPNetscapeFuncs* npFuncs) { 
# ifdef DEBUG 
    cout << "NP_Initialize\n"; 
    MessageBox(NULL, "NP_Initialize", "Plugin-message", 0); 
# endif // DEBUG 
    return NPERR_NO_ERROR; 
} 

NPError NP_Shutdown() { 
# ifdef DEBUG 
    cout << "NP_Shutdown\n"; 
# endif // DEBUG 
    return NPERR_NO_ERROR; 
} 

// - Plugin Execution ----------------- 
// - ------ --------- ----------------- 

NPError NP_New(NPMIMEType pluginType, 
       NPP   npp, 
       uint16_t  mode, 
       int16_t  argc, 
       char*  argn[], 
       char*  argv[], 
       NPSavedData* saved) { 
# ifdef DEBUG 
    cout << "NP_New\n"; 
# endif 

    if (!npp) 
     return NPERR_INVALID_INSTANCE_ERROR; 

    return NPERR_NO_ERROR; 
} 

Я компиляции кода с использованием г ++ 4.4.1

g++ npp_test.cpp -I"D:\include\xulrunner" -shared -Wall -Wextra -o "npp_test.dll" 

компилирует хорошо, но, глядя на содержание библиотек DLL с помощью DLL Expat, тем имена не являются такими, как ожидалось:

================================================== 
Function Name  : _get_output_format 
Address   : 0x6889c658 
Relative Address : 0x0001c658 
Ordinal   : 5 (0x5) 
Filename   : npp_test.dll 
Type    : Exported Function 
Full Path   : C:\Users\niklas\Desktop\npp_test.dll 
================================================== 

================================================== 
Function Name  : _Z6NP_NewPcP4_NPPtsPS_S2_P12_NPSavedData 
Address   : 0x68881270 
Relative Address : 0x00001270 
Ordinal   : 4 (0x4) 
Filename   : npp_test.dll 
Type    : Exported Function 
Full Path   : C:\Users\niklas\Desktop\npp_test.dll 
================================================== 

================================================== 
Function Name  : [email protected] 
Address   : 0x688811d8 
Relative Address : 0x000011d8 
Ordinal   : 1 (0x1) 
Filename   : npp_test.dll 
Type    : Exported Function 
Full Path   : C:\Users\niklas\Desktop\npp_test.dll 
================================================== 

================================================== 
Function Name  : [email protected] 
Address   : 0x68881205 
Relative Address : 0x00001205 
Ordinal   : 2 (0x2) 
Filename   : npp_test.dll 
Type    : Exported Function 
Full Path   : C:\Users\niklas\Desktop\npp_test.dll 
================================================== 

================================================== 
Function Name  : [email protected] 
Address   : 0x6888124f 
Relative Address : 0x0000124f 
Ordinal   : 3 (0x3) 
Filename   : npp_test.dll 
Type    : Exported Function 
Full Path   : C:\Users\niklas\Desktop\npp_test.dll 
================================================== 

Не следует ли их называть как источник? Когда «expating» java-dll для firefox, например, имена прекрасны. Использование DLLEXPORT в

#define DLLEXPORT __declspec(dllexport) 

не работает. Но это, по крайней мере, «удаляет» функции _get_output_format и _Z6NP_NewPcP4_NPPtsPS_S2_P12_NPSavedData от экспорта, Почему они экспортируются, когда не используется DLLEXPORT.

Почему имена экспортируемых функций имеют дополнительный @4/@0 суффикс? Я думаю, что число после @ указывает количество байтов, которые функция принимает в качестве аргументов, но при экспорте это фактически не должно содержаться в имени, правильно?

+0

Некоторые из имен C++ исковерканные имена функций. Вероятно, '@ 4' является номером ревизии библиотеки. –

+3

'@ 4' - это количество байтов, которое' __stdcall' fuction необходимо удалить из стека после вызова. – Dialecticus

+0

Вы определили 'DLLEXPORT', но затем никогда не использовали его. –

ответ

3

@ (stack_size_of_params) это имя украшение для STDCALL Экстерн функции «C». Я больше знаком с инструментами Microsoft, но я убежден, что вам нужно будет использовать файл .def для экспорта неразделенных имен для функций, которые используют stdcall.

Редактировать: Веб-поиск предлагает - опция командной строки для командной строки для инструментов GNU может избежать необходимости в иркс-файлах .def.

+0

Спасибо за ваш ответ. Просто быстро: как я могу указать файл .def для g ++, чтобы я мог проверить ваше предложение? Просто не могу найти вариант. ** Изменить: A, просто указывая как входной файл. :) –

+0

Это работает! Отлично, спасибо. Тем не менее, немного неудобно с этим '.def'-файлом. –

+1

Я действительно мало знаю о g ++. Websearch предлагает --kill-at удалить при оформлении. Это означало бы отсутствие необходимости в .def. Или просто укажите .def в командной строке в g ++ или ld. –

1

Это C++ поэтому имена искажаются, если вы не объявите их также с экстерном «C»

+0

Использование '#define DLLEXPORT extern 'C" __declspec (dllexport) 'также не устраняет проблему, к сожалению. –

+1

IIRC 'extern" C "" просто изменяет тип управления именами. Вам нужно '.def' для экспорта вашей функции с любым именем, которое вы предпочитаете. –

1

Если вы хотите контролировать имена экспортируемых функций, используйте раздел EXPORTS в файле определения компоновщика (* .def), а не __declspec(dllexport).

+0

@ Давид Хеффернан был быстрее, извините. ;) Но спасибо за ваш ответ, это действительно решение головоломки. –

1

С GCC NP_EXPORT уже заботится о видимости символов и т.д .:

extern "C" NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs); 

Это работает только для Unixes, хотя, так что для GCC на Windows, вам придется set the visibilities yourself.

В Windows/VC++ вы дополнительно должны указать экспорт в виде файла .def как упоминалось:

NP_GetEntryPoints @1 
NP_Initialize  @2 
NP_Shutdown   @3 
Смежные вопросы