我正在尝试构建一个用于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。我不确定为什么。
任何帮助都将不胜感激。
答案 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.dll
和msvcrt.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的大小。