为什么导出的函数在DLL中没有正确命名?

时间:2012-01-15 22:48:38

标签: c++ dll npapi dllexport

我正在尝试使用NPAPI为firefox做一个小测试插件。到目前为止,这是我的代码:

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

我正在使用 g ++ 4.4.1

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

编译正常,但使用 DLL Expat 查看DLL内容时,名称不符合预期:

==================================================
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
==================================================

不应该像在源中一样调用它们吗?例如,当“expating”firefox的java-dll时,名称就可以了。使用 DLLEXPORT 作为

#define DLLEXPORT __declspec(dllexport)

也不起作用。但是,这至少会“删除”导出的函数_get_output_format_Z6NP_NewPcP4_NPPtsPS_S2_P12_NPSavedData在不使用 DLLEXPORT 的情况下导出它们

为什么导出的函数名称后缀为@4 / @0?我想@之后的数字指定了函数作为参数的字节数,但是在导出时,这实际上不应该包含在名称中,对吗?

4 个答案:

答案 0 :(得分:3)

@(stack_size_of_params)是stdcall extern“C”函数的名称修饰。我对Microsoft工具比较熟悉,但我相信您需要使用.def文件导出使用stdcall的函数的未修饰名称。

编辑:Websearch建议,GNU工具的-kill-at命令行选项可以避免使用令人厌烦的.def文件。

答案 1 :(得分:1)

这是C ++,所以除非你用extern“C”

声明它们,否则名称会被破坏

答案 2 :(得分:1)

如果要控制导出的函数名称,请使用链接器定义文件(* .def)中的EXPORTS部分,而不是__declspec(dllexport)

答案 3 :(得分:1)

GCC NP_EXPORT已经处理了符号可见性,例如:

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

这仅适用于Unix,因此对于Windows上的GCC,您必须set the visibilities yourself

在Windows / VC ++上,您还必须在.def文件中指定导出,如上所述:

NP_GetEntryPoints   @1
NP_Initialize       @2
NP_Shutdown         @3