构建包含Mozilla js-ctypes库的DLL

时间:2013-12-04 15:27:00

标签: gcc dll firefox-addon mozilla jsctypes

我正在尝试构建一个用于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);
    }
}

我按照这里的说明操作:Build a DLL to be used by Mozilla js-ctypes

问题在于,当我尝试包含不同的库时,js-ctypes之后无法读取DLL:
[10:20:53.575] Error: couldn't open library C:\Users\admin\workspaces\Extensions\formfinder\components\test.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。我不确定为什么。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

我不太了解被问到的内容,但可能是为什么Cygwin gcc(或mingw-w64 gcc)正在生成一个你不能ctypes.open()的DLL。

Cygwin gcc生成的DLL对某些Cygwin DLL有外部依赖关系,至少cygwin1.dll提供posix抽象。 将这些DLL与您的附加组件一起发送是一件痛苦的事,并不是一件理智的事情。

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

好的,现在是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的输出。

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

$ 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位并遵循许可证),或避免任何可能产生异常或需要{{1 }}。 或者你可以静态链接这些东西:

stdlibc++

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