构建一个包含 Mozilla js-ctypes 库的 DLL



我正在尝试构建一个用于Mozilla Firefox扩展的DLL。我在Windows 7中使用Cygwin。我有 C 代码工作正常,它构建正常:

#include<stdio.h>
#include<windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
  return TRUE;
}
extern "C"
{
    __declspec(dllexport) int add(int a,int b) //int a,int b
    {
        return(a+b);
    }
}

我按照这里的说明操作:构建一个供Mozilla js-ctypes使用的DLL。

问题是,当我尝试包含不同的库时,js-ctypes 之后无法读取 DLL:
[10:20:53.575] Error: couldn't open library C:UsersadminworkspacesExtensionsformfindercomponentstest.dll @ chrome://formfinder/content/overlay.js:104

我添加到 C 文件中的所有内容都#include <ZZ.h>在顶部,然后由 make 命令补充:

i686-w64-mingw32-g++ -c -I/usr/local/include/NTL -I/usr/local/include test.cc  
i686-w64-mingw32-g++ -shared -o test.dll test.o -Wl,--out-implib,libmylib.dll -Wl,-e_DllMain@12

我使用的是i686-w64-mingw32-g++而不是gcc/g++因为否则无法打开 DLL。我不知道为什么。

任何帮助将不胜感激。

不太明白问了什么,但可能为什么 Cygwin gcc(或 mingw-w64 gcc(正在生成您无法ctypes.open()的 DLL

由Cygwin gcc生成的DLL确实对某些Cygwin DLL具有外部依赖性,至少cygwin1.dll提供了posix抽象。将这些 DLL 与附加组件一起交付是一种痛苦,并不是一件理智的事情。

您需要使用mingw编译器(例如i686-w64-mingw32-g++编译器(。您也可以改用Microsoft或英特尔编译器。

好的,mingw-w64 现在是:

$ i686-w64-mingw32-g++ -shared -o test_add.dll test_add.cc
$ objdump -p test_add.dll
The Import Tables (interpreted .idata section contents)
...
DLL Name: KERNEL32.dll
...
DLL Name: msvcrt.dll
...
The Export Tables (interpreted .edata section contents)
...
[Ordinal/Name Pointer] Table
        [   0] add

好的,我们的DLL导入kernel32.dllmsvcrt.dll,没有任何意外,并且还导出了我们的add

让我们试试吧,然后:

var lib = ctypes.open("C:\cygwin\home\user\test_add.dll");
try {
    try {
        var adder = lib.declare("add", ctypes.default_abi, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t);
        console.log(adder(3,5));
    }
    catch(ex) {
        console.error(ex, ex.message);
    }
}
finally {
    lib.close();
}

生成输出:8

接下来,应启用所有二进制文件。

$ peflags -v test_add.dll
test_add.dll: coff(0x2106[+executable_image,+line_nums_stripped,+32bit_machine,+dll]) pe(0x0000)

事实证明,它不是(没有动态基础(

因此,让我们改进链接器命令:

$ i686-w64-mingw32-g++ -shared -o test_add.dll test_add.cc -Wl,-nxcompat,-dynamicbase
$ peflags -v test_add.dll
test_add.dll: coff(0x2106[+executable_image,+line_nums_stripped,+32bit_machine,+dll]) pe(0x0140[+dynamicbase,+nxcompat])

那好吧。

但不幸的是,这还不是全部。当编译C++并使用某些功能时,链接器将自动在stdlibc++中链接,例如在使用std::string时。

向我们的源代码添加std::string,重新编译/重新链接,以及另一个objdump告诉我们:

DLL Name: libgcc_s_sjlj-1.dll
vma:  Hint/Ord Member-Name Bound-To
7470       16  _Unwind_SjLj_Register
7488       17  _Unwind_SjLj_Resume
74a0       19  _Unwind_SjLj_Unregister
DLL Name: libstdc++-6.dll
vma:  Hint/Ord Member-Name Bound-To
74bc      743  _ZNSaIcEC1Ev
74cc      746  _ZNSaIcED1Ev
74dc     1080  _ZNSsC1EPKcRKSaIcE
74f4     1105  _ZNSsD1Ev
7500     3535  __gxx_personality_sj0

在这种情况下,您还必须发送这些库(确保peflags ASLR 位并遵循许可证(,或者避免任何可能产生异常或需要stdlibc++的内容。或者你可以静态链接这些东西:

i686-w64-mingw32-g++ -shared -o test_add.dll test_add.cc -Wl,-nxcompat,-dynamicbase -static-libgcc -static-libstdc++

当然,静态链接会放大输出 DLL 的大小。

最新更新