2014-09-11 234 views
1

我已經閱讀過大量關於如何解決我的問題的文章,教程和指導 - 但仍然沒有收穫。我只是不能投入工作。我的目標很簡單:我想使用Cygwin gcc工具編譯DLL文件,然後在MSVC2010中使用它。我實際上是想用我自己的DLL代碼來做,但爲了簡單起見 - 我已經嘗試了Cygwin網站上的基本示例 - 並且失敗了。在Visual Studio 2010中使用用Cygwin編譯的DLL

到目前爲止我所做的: (大部分是從Cygwin的用戶指南採取DLL section

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

    #include <stdio.h> 
    
    int hello() { 
        printf ("Hello World!\n"); 
    } 
    
  2. 編譯mydll.c到使用和gcc -shared -o mydll.dll mydll.o

  3. 在Visual Studio中打開一個空的Win32控制檯項目,用下面的代碼(在hereOleg的代碼取碼,並根據thistest.c

    #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(); 
    } 
    
  4. 套裝Windows系統上的路徑變量包含「Cygwin \ bin \」目錄。

  5. 構建&運行。

我結束了以下異常: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不同的地址。導致異常的代碼中的行是調用hello func,在DLL文件中。

而在你走之前說什麼關於extern "C"__declspec(dllimport/dllexport) - 不會幫助。我已經嘗試過所有這些,但它沒有幫助。(雖然,AFAIK - 我根據MS使用Explicit Linking,或者根據UNIX使用Dynamic Loading,所以__declspec(dllimport/dllexport)不是必需的)。

我真的希望這個問題是不是在棧定義,躺在over here

「請確保您有在臨時空間4K你棧底」

因爲我不知道如何在MSVC2010上做到這一點(顯然,Oleg也沒有......:)

現在,我知道有一個直接引用我的問題在Hans Passant的話超過here - 仍然 - 我無法理解如何解決我的問題。

更新:我正在更新這個,因爲我想我知道是什麼原因導致問題,我只是不知道如何解決它。原諒我,Arkady,但我真的不認爲它必須對你所提到的所有事情做任何事情。我正在拿真的很簡單.DLL文件,只有一個功能,所以沒有什麼'包裝'在那裏..
無論如何,我認爲我的問題是使用msvcrt.dll文件,而不是什麼規定here

Q:我可以用兩個MSVCRT * .DLL和cygwin1.dll鏈接?
答:不,你必須使用一種或另一種,它們是互斥的。

我知道我對鏈接他們兩個,我只是不知道如何說服Visual Studio中只單獨對cygwin1.dll鏈接..

我一個並欣賞回答這個。

+0

http://www.mingw。org/wiki/What_is_a_DLL_and_How_Do_I_Create_or_Use_One可能有用... – rogerdpack 2015-08-21 21:53:41

回答

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 deallocator發佈。

它必須正常工作,因爲通過調用GlobalFunction將在DLL內部初始化,並且會有析構函數,在DLL內部實現。儘管如此,我還是願意避免它,只用簡單的數據和全局函數就可以使用C風格。

4)你也必須確定int在你的gcc和int在你的VS2010有相同的大小。你設置相同的架構。例如,爲了避免這個問題,你應該使用int32_t。

5)你應該確保所有導出的dll函數不會拋出異常。完全一樣。由相同的記憶問題 - 原因。

相關問題