Why are the exported functions not named properly

2019-08-11 00:45发布

问题:

I'm trying to do a little test-plugin using NPAPI for firefox. This is my code so far:

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

I'm compiling the code using g++ 4.4.1

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

Compiles fine, but looking at the DLLs content using DLL Expat, the names are not as expected:

==================================================
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     : NP_GetEntryPoints@4
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     : NP_Initialize@4
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     : NP_Shutdown@0
Address           : 0x6888124f
Relative Address  : 0x0000124f
Ordinal           : 3 (0x3)
Filename          : npp_test.dll
Type              : Exported Function
Full Path         : C:\Users\niklas\Desktop\npp_test.dll
==================================================

Shouldn't they be called like in the source? When "expating" the java-dll for firefox, just for example, the names are fine. Using DLLEXPORT as

#define DLLEXPORT __declspec(dllexport)

doesn't work either. But this at least "removes" the functions _get_output_format and _Z6NP_NewPcP4_NPPtsPS_S2_P12_NPSavedData from being exported, whyever they are exported when not using DLLEXPORT.

Why are the exported functions names with an additional @4/@0 suffix ? I guess the number after the @ specifies the number of bytes the function takes as arguments, but when exporting, this actually shouldn't be contained in the name, right ?

回答1:

The @(stack_size_of_params) is a name decoration for stdcall extern "C" functions. I'm more familiar with Microsoft tools but my belief is that you will need to use a .def file to export undecorated names for functions that use stdcall.

Edit: Websearch suggests --kill-at command line option for the GNU tools could avoid need for irksome .def files.



回答2:

This is C++ so names are mangled unless you declare them also with extern "C"



回答3:

If you want control over exported function names, use an EXPORTS section in a linker definition file (*.def), not __declspec(dllexport).



回答4:

With GCC NP_EXPORT already takes care of the symbol visibility, e.g.:

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

That only works for Unixes though, so for GCC on Windows you'll have to set the visibilities yourself.

On Windows/VC++ you additionally have to specify the exports in a .def file as mentioned:

NP_GetEntryPoints   @1
NP_Initialize       @2
NP_Shutdown         @3