我已经阅读了大量有关如何解决问题的文章,教程和说明 - 但仍然没有收获。我无法将其付诸实践。
我的目标非常简单:我想使用Cygwin gcc工具编译DLL文件,然后在MSVC2010中使用它。我实际上想用我自己的DLL代码来做这件事,但为了简单起见 - 我已经在Cygwin的网站上尝试了一个非常基本的例子 - 并且也失败了。
到目前为止我做了什么: (大部分来自Cygwin用户指南,DLL section)
创建mydll.c
文件如下:
#include <stdio.h>
int hello() {
printf ("Hello World!\n");
}
使用mydll.c
和mydll.dll
gcc -c mydll.c
编译为gcc -shared -o mydll.dll mydll.o
在Visual Studio中打开一个空的Win32控制台项目,其代码为test.c
(代码取自Oleg中here的代码,并且基于在this):
#include <windows.h>
typedef int (*PFN_HELLO)();
typedef void (*PFN_CYGWIN_DLL_INIT)();
int main()
{
PFN_HELLO fnHello;
HMODULE hLib, h = LoadLibrary(TEXT("cygwin1.dll"));
PFN_CYGWIN_DLL_INIT init = (PFN_CYGWIN_DLL_INIT)GetProcAddress(h,"cygwin_dll_init");
init();
hLib = LoadLibrary (TEXT("D:\\test\\mydll.dll"));
fnHello = (PFN_HELLO) GetProcAddress (hLib, "hello");
return fnHello();
}
在Windows系统上设置路径变量以包含&#34; Cygwin \ bin \&#34; 。目录
Build&amp;运行
我最终遇到以下异常:0xc0000005: Access violation reading location 0x003a0048.
这是完整的MSVC2010调试输出:
'CygwinDLLTest.exe': Loaded 'C:\Users\xxxx\Documents\Visual Studio 2010\Projects\CygwinDLLTest\Debug\CygwinDLLTest.exe', Symbol loaded.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\kernelBase.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\msvcr100d.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'D:\Cygwin\bin\cygwin1.dll', Binary was not built with debug information.
cYgFFFFFFFF 6119F510 0cYgstd 0x27a70b d 3'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\user32.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\gdi32.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\lpk.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\usp10.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\msvcrt.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\advapi32.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\sechost.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\rpcrt4.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\sspicli.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\cryptbase.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\imm32.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'C:\Windows\SysWOW64\msctf.dll', cannot find or open the PDB file.
'CygwinDLLTest.exe': Loaded 'D:\test\mydll.dll', Binary was not built with debug information.
First-chance exception at 0x611075a8 in CygwinDLLTest.exe: 0xc0000005: Access violation reading location 0x003a0048
Unhandled exception at 0x611075a8 in CygwinDLLTest.exe: 0xc0000005: Access violation reading location 0x003a0048
The program '[784] CygwinDLLTest.exe: Native' has exited with code 0 (0x0).
现在,重要的是要注意问题是没有加载这些DLL,因为他们的处理程序都有一个不同于NULL的地址。代码中导致异常的行是在DLL文件中调用hello func 。
在您去谈论有关extern "C"
或__declspec(dllimport/dllexport)
的任何内容之前,我们不会给您带来任何帮助。我已经尝试了所有这些并且它没有帮助。(尽管,AFAIK - 我在MS方面使用Explicit Linking,或{{3就UNIX而言,__declspec(dllimport/dllexport)
不是必需的。)
我真的希望问题不在于堆栈定义,就像躺在Dynamic Loading:
&#34;确保堆栈底部有4K的临时空间&#34;
因为我不知道如何在MSVC2010上实现这一点(显然,over here ......都不会......)
现在,我知道在Oleg关于Hans Passant的单词中直接引用了我的问题 - 仍然 - 我无法理解如何解决我的问题
更新我更新了这个,因为我想我知道导致问题的原因,我只是不知道如何解决它。原谅我,here,但我真的不认为它必须对你提到的所有内容做任何事情。我正在使用非常简单的 .dll文件,只有一个函数,因此没有任何内容可以包含&#39;有..
无论如何,我认为我的问题是使用msvcrt.dll文件,而不是Arkady所述:
问:我可以同时连接MSVCRT * .DLL和cygwin1.dll吗? 答:不,你必须使用其中一种,它们是相互排斥的。
我知道我已经联系了他们两个,我只是不知道如何说服Visual Studio仅针对cygwin1.dll链接..
我会回答这个问题。
答案 0 :(得分:0)
要使用gcc创建DLL并在Visual Studio中使用它,您需要执行以下步骤:
1)检查您的包装是否相同。我的意思是:
#pragma pack(push, N)
#pragma pack(pop)
对于要导出的所有结构,函数和数据类型。避免不同的默认数据打包。
2)检查您是否使用外部头文件(即您的导出头不包含从外部头文件中获取的任何内容)。我的意思是“windows.h”在VS2010和CygWin中可能会有所不同。通常差异并不重要,但由于它存在,您可能会遇到问题。 与STL和其他版本相同,版本可能不会(也不会!)兼容,因此您将遇到内存问题。
3)检查您是否只导出简单结构和全局函数。所以,你真的必须导出类似C的界面。 理论告诉你,如果你还要导出抽象接口,例如:
#pragma pack(push, 4)
struct A
{
virtual ~A() {}
virtual int32_t DoA() = 0;
virtual int32_t PrepareA(const char* settings) = 0;
};
void GlobalFunction(A** ret);
#pragma pack(pop)
或者完全避免使用虚拟析构函数,并添加全局函数,该函数将释放在DLL中分配的对象的内存。由于gcc和msvc-10.0将具有不同的数据管理,因此所有使用gcc分配器分配的都必须由gcc deallocators释放。
它必须正常工作,因为将通过调用GlobalFunction在DLL中初始化,并且将在DLL内部实现析构函数。尽管如此,我仍然愿意避免它,使用类似C的风格,只需要简单的数据和全局函数。
4)你还必须确保你的gcc和你的VS2010的int具有相同的大小。你设置相同的架构。为了避免这个问题,你应该使用int32_t,例如。
5)你应该确保所有导出的dll函数都不会抛出异常。完全没有。由相同的记忆问题 - 原因。