使用在Visual Studio 2010中使用Cygwin编译的DLL

时间:2014-09-11 12:22:02

标签: c++ visual-studio-2010 gcc dll cygwin

我已经阅读了大量有关如何解决问题的文章,教程和说明 - 但仍然没有收获。我无法将其付诸实践。

我的目标非常简单:我想使用Cygwin gcc工具编译DLL文件,然后在MSVC2010中使用它。我实际上想用我自己的DLL代码来做这件事,但为了简单起见 - 我已经在Cygwin的网站上尝试了一个非常基本的例子 - 并且也失败了。

到目前为止我做了什么: (大部分来自Cygwin用户指南,DLL section

  1. 创建mydll.c文件如下:

    #include <stdio.h>
    
    int hello()    {
      printf ("Hello World!\n");
    }
    
  2. 使用mydll.cmydll.dll

  3. gcc -c mydll.c编译为gcc -shared -o mydll.dll mydll.o
  4. 在Visual Studio中打开一个空的Win32控制台项目,其代码为test.c(代码取自Oleghere的代码,并且基于在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();
    }
    
  5. 在Windows系统上设置路径变量以包含&#34; Cygwin \ bin \&#34; 。目录

  6. Build&amp;运行

  7. 我最终遇到以下异常: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链接..

    我会回答这个问题。

1 个答案:

答案 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函数都不会抛出异常。完全没有。由相同的记忆问题 - 原因。