在Visual Studio 2010中使用Cygwin编译的DLL [英] Using DLL compiled with Cygwin inside Visual Studio 2010

查看:511
本文介绍了在Visual Studio 2010中使用Cygwin编译的DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了大量的文章,教程和关于如何解决我的问题的说明,但仍然没有收获。我只是不能把它变成工作。

I've read already tremendous amount of articles, tutorials, and instructions about how to solve my problem - but still - no gain. I just can't put it into work.

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

My goal is pretty simple: I want to compile a DLL file using Cygwin gcc tool, and then use it within MSVC2010. I'm actually want to do it with my own DLL code, but as for simplicity - I've tried the very basic example on Cygwin's site - and failed with that too..

我迄今为止所做的工作:
(大部分来自Cygwin用户指南, DLL部分

What I've done so far: (Most is taken from Cygwin User's Guide, DLL section)


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

#include <stdio.h>

int hello()    {
  printf ("Hello World!\n");
}


  • 编译 mydll.c mydll.dll 使用 gcc -c mydll.c gcc - 共享-o mydll.dll mydll.o

    在Visual Studio中打开一个空的Win32控制台项目,其代码如下: code> test.c (代码取自 Oleg 的代码此处,并基于):

    Opened an empty Win32 Console project in Visual Studio, with the following code as test.c (code taken from Oleg's code in here, and based on 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系统中设置路径变量以包含Cygwin\ bin \目录。

  • Set the path variable on Windows system to include "Cygwin\bin\" directory.

    Build&

    Build & Run.

    最后我出现了以下异常: 0xc0000005:访问冲突读取位置0x003a0048

    I ended up with the following exception: 0xc0000005: Access violation reading location 0x003a0048.

    以下是完整的MSVC2010调试输出:

    Here is the full MSVC2010 Debug Output:

    '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的

    Now, it's important to notice that the problem wasn't loading those DLL's, as their handlers all got an address different from NULL. The line in the code that cause the exception, was the call to the hello func, inside the DLL file.

    在你去之前,再说一下关于 externC __ declspec(dllimport / dllexport) - 不会帮助。我已经尝试了所有这些,它没有帮助。(虽然,AFAIK - 我正在使用显式链接根据MS或动态加载在UNIX中,所以 __ declspec(dllimport / dllexport)不是必需的)。

    And before you go and say anything about extern "C" or __declspec(dllimport/dllexport) - won't help. I've tried all of them and it didn't help. (although, AFAIK - I'm using Explicit Linking in terms of MS, or Dynamic Loading in terms of UNIX, so __declspec(dllimport/dllexport) is not necessary).

    我真的希望问题不在堆栈定义,因为说谎在这里

    I'm really hope the problem is not at the stack definition, as lying over here:


    确保你的4K空间在底部你的堆栈

    "Make sure you have 4K of scratch space at the bottom of your stack"

    因为我不知道如何使MSVC2010发生这样的事情(显然, https://stackoverflow.com/users/315935/oleg\"> Oleg ...:)

    Because I've no clue how to make this happen on MSVC2010 (and apparently, neither do Oleg...:)

    现在,我知道有一个直接的引用我的问题在汉斯Passant 的话在这里 - 仍然 - 我无法理解如何解决我的问题。

    Now, I know there's a direct reference to my problem in Hans Passant's words over here - still - I couldn't understand how to solve my problem.

    更新:我正在更新这个,因为我觉得我知道是什么原因造成的,我只是不知道该怎么解决。并原谅我, Arkady ,但我真的不认为它必须对你提到的所有事情做任何事情。我正在使用真正简单的 .dll文件,只有一个功能,所以没有什么可以包装在那里..

    无论如何,我认为我的问题是使用msvcrt .dll文件,而不是这里所示: / p>

    UPDATE: I'm updating this, because I think I know what cause the problem, I just don't know how to solve it. And forgive me, Arkady, but I really don't think that it has to do anything with all what you mentioned. I was taking about really simple .dll file, with only one function, so there's nothing to 'wrap' there..
    Anyway, I think my problem is the use of msvcrt.dll file, as opposed to what stated here:


    问:我可以链接MSVCRT * .DLL和cygwin1.dll吗?

    A:不,你必须使用一个或另一个,它们是相互排斥的。

    Q: Can I link with both MSVCRT*.DLL and cygwin1.dll?
    A:No, you must use one or the other, they are mutually exclusive.

    我知道我正在链接两者,我只是不知道如何说服Visual Studio仅与cygwin1.dll链接。

    I know I'm linking against both of them, I just don't know how to convince Visual Studio to link only against cygwin1.dll alone..

    我会为此提供一个答案。

    I'll appriciate an answer to this.

    推荐答案

    要使用gcc创建DLL并在Visual Studio中使用它,您需要遵循以下步骤:

    To create DLL using gcc and use it in Visual Studio, you need to follow next steps:

    1检查你的包装是否相同。我的意思是:

    1) check that your packing is same. I mean:

    #pragma pack(push, N) 
    #pragma pack(pop)
    

    对于要导出的所有结构,函数和数据类型。为了避免不同的默认数据打包。

    For all structures, functions and data types you want to export. To avoid different default data packing.

    2)检查你不使用外部头文件(即导出头不包含从外部头部取得的任何内容)文件)。我的意思是windows.h可能和会在VS2010和CygWin不同。通常差异并不重要,但由于存在,您可能会遇到问题。
    与STL和其他版本相同,版本可能不会(并且不会)兼容,所以您将有内存问题。

    2) check that you don't use external header files (i.e. your exporting header don't contains anything that is taken from external header files). I mean "windows.h" may be and will be different in VS2010 and CygWin. Usually difference is not important, but since it exist, you may have problems with it. Same with STL and others, versions may not (and will not!) be compatibility, so you will have problems with memory.

    3)检查你导出简单的结构和全局功能。所以,你真的要导出类似C的界面。
    理论指出,如果您还将导出抽象接口,例如:

    3) check that you export just simple structures and global functions. So, you really have to export C-like interface. Theory tells that if you will export also abstract interfaces, such as in example:

    #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发布。

    Or avoid virtual destructor at all, and add global function that will release memory of objects who were allocated in DLL. Because gcc and msvc-10.0 will have different data management, so all allocated with gcc allocators have to be released by gcc deallocators.

    它必须正常工作,因为将通过调用GlobalFunction在DLL内部初始化,并在DLL内实现析构函数。不过,我会提供避免它,只使用简单的数据和全局功能的C样式。

    it have to work correctly, because will be initialized inside DLL by calling GlobalFunction, and will have destructor, realized inside DLL. Still, I would offer to avoid it, using C-like style with just simple data and global functions.

    4)你还必须确保int在你的gcc和int在你的VS2010具有相同的大小。你设置相同的架构。为了避免这个问题你应该使用int32_t,例如。

    4) You also have to be sure int at your gcc and int at your VS2010 have same size. And you set same architecture. To avoid that problem you should use int32_t, for example.

    5)你应该确保所有导出的dll函数都不会抛出异常。在所有相同的内存问题原因。

    5) And you should be sure that all exported dll functions don't throws exceptions. At all. By same memory problem-reason.

    这篇关于在Visual Studio 2010中使用Cygwin编译的DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆