2014-09-11 2 views
1

Я читал уже огромное количество статей, руководств и инструкций о том, как решить мою проблему, но все же - нет выгоды. Я просто не могу положить его в работу.Использование DLL, скомпилированного с Cygwin внутри Visual Studio 2010

Моя цель довольно проста: я хочу скомпилировать DLL-файл с помощью инструмента Cygwin gcc, а затем использовать его в MSVC2010. Я действительно хочу сделать это с помощью своего собственного DLL-кода, но что касается простоты - я пробовал самый простой пример на сайте Cygwin - и с этим тоже не справился.

Что я сделал до сих пор: (Большинство взят из Руководства пользователя Cygwin, DLL section)

  1. Созданный mydll.c файл следующим образом:

    #include <stdio.h> 
    
    int hello() { 
        printf ("Hello World!\n"); 
    } 
    
  2. Составитель mydll.c в mydll.dll с использованием gcc -c mydll.c и gcc -shared -o mydll.dll mydll.o

  3. Открыт пустой проект Win32 Console в Visual Studio, с помощью следующего кода в test.c (код взят из кода Oleg «s в 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(); 
    } 
    
  4. Set переменную пути в системе Windows, чтобы включить каталог «Cygwin \ bin \».

  5. Построение & Запуск.

Я закончил тем, за исключением следующего: 0xc0000005: Access violation reading location 0x003a0048.

Вот полный 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). 

Теперь, важно отметить, что эта проблема не была загрузки этих библиотек , так как их обработчики получили адрес, отличный от NULL. Строкой в ​​коде, вызывающим исключение, был вызов hello func, внутри DLL-файла.

А перед тем, как пойти и сказать что-нибудь о extern "C" или __declspec(dllimport/dllexport) - не поможет. Я пробовал все из них , и это не помогло. (хотя, AFAIK - я использую Explicit Linking с точки зрения MS или Dynamic Loading с точки зрения UNIX, поэтому __declspec(dllimport/dllexport) не требуется).

Я действительно надеюсь, что проблема не в определении стека, как ложь over here:

«Убедитесь, что у вас есть 4К рабочего пространства в нижней части стека»

Потому что я понятия не имею, как это произошло на MSVC2010 (и, по-видимому, ни Oleg ...:)

Теперь, я знаю, что есть прямая ссылка на мою проблему в словах Hans Passant над here - все еще - я не мог понять, как решить мою проблему.

ОБНОВЛЕНИЕ: Я обновляю это, потому что я думаю, что знаю, в чем причина проблемы, я просто не знаю, как ее решить. И простите меня, Arkady, но я действительно не думаю, что он должен что-либо делать со всем, что вы упомянули. Я принимал около действительно простой файл .dll с одной функцией, поэтому там нечего «обворачивать».
В любом случае, я думаю, что моя проблема заключается в использовании файла msvcrt.dll, в отличие от того, что указано here :

В: Можно ли связать как с MSVCRT * .DLL, так и с cygwin1.dll?
A: Нет, вы должны использовать тот или иной, они являются взаимоисключающими.

Я знаю, связывая против обоих из них, я просто не знаю, как убедить Visual Studio, чтобы связать только с одной только cygwin1.dll ..

Я appriciate ответ на этот ,

+0

http: //www.mingw.org/wiki/What_is_a_DLL_and_How_Do_I_Create_or_Use_One может быть полезно ... – rogerdpack

ответ

0

Для создания библиотеки DLL с помощью GCC и использовать его в 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-деллалокаторами.

он должен работать правильно, потому что он будет инициализирован внутри DLL, вызвав GlobalFunction, и будет иметь деструктор, реализованный внутри DLL. Тем не менее, я бы предложил избежать этого, используя стиль C-типа с помощью простых данных и глобальных функций.

4) Вы также должны быть уверены, что int на вашем gcc и int на вашем VS2010 имеет такой же размер. И вы устанавливаете ту же архитектуру. Чтобы избежать этой проблемы, вы должны использовать int32_t, например.

5) И вы должны быть уверены, что все экспортированные DLL-функции не выдают исключений. Вообще. По той же проблеме-причине.

Смежные вопросы