Совместимость Dll между компиляторами

Спать 5 секунд, основываясь на коде RamRaider:

<?php
for($x=0; $x<100; $x++){
    echo $x . ' ';
    if( $x % 10 == 0 )
    {
        sleep(5);
    }
}
?>
9
задан dandan78 23 December 2014 в 08:31
поделиться

7 ответов

Необходимо смочь смешать модули, созданные с различными компиляторами, если Вы понижаете свои ожидания и придерживаетесь простых функций.

Путем классы и виртуальные функции ведут себя, определяется стандартом C++, но способ, которым это реализовано, до компилятора. В этом случае я знаю, что VC ++ создает объекты, которые имеют виртуальные функции с "vtable" указателем в первых 4 байтах объекта (я принимаю 32-разрядный), и это указывает на таблицу указателей на точки входа метода.

Так строка: dllclass->PrintSomething(); на самом деле эквивалентно чему-то как:

struct IClassVTable {
    void (*pfIClassDTOR)           (Class IClass * this) 
    void (*pfIRefCountedAddRef)    (Class IRefCounted * this);
    void (*pfIRefCountedRelease)   (Class IRefCounted * this);
    void (*pfIClassPrintSomething) (Class IClass * this);
    ...
};
struct IClass {
    IClassVTable * pVTab;
};
(((struct IClass *) dllclass)->pVTab->pfIClassPrintSomething) (dllclass);

Если g ++ компилятор реализует таблицы виртуальной функции всегда по-другому по сравнению с VC MSFT ++ - поскольку это свободно сделать и все еще быть совместимым к стандарту C++ - это просто откажет, как Вы продемонстрировали. VC ++ код ожидает, что указатели функции будут в особенности местами в памяти (относительно объектного указателя).

Это становится более осложненным наследованием, и действительно, действительно, сложный со множественным наследованием и виртуальным наследованием.

Microsoft была очень общедоступна о способе, которым VC ++ реализует классы, таким образом, можно написать код, который зависит от него. Например, много заголовков COM-объекта, распределенных MSFT, имеет и C и привязку C++ в заголовке. Привязка C выставляет свою vtable структуру как мой код выше, делает.

С другой стороны, GNU - IIRC - оставил открытым опция использования различных реализаций в различных выпусках и просто гарантии программ созданный с, он - компилятор (только!) будет соответствовать стандартному поведению,

Короткий ответ должен придерживаться простых функций C-стиля, структуры POD (Простые Данные; т.е. никакие виртуальные функции), и указатели на непрозрачные объекты.

9
ответ дан 4 December 2019 в 08:02
поделиться

Вы почти наверняка напрашиваетесь на неприятности, если Вы делаете это - в то время как другие комментаторы корректны, что ABI C++ может быть тем же в некоторых случаях, эти две библиотеки используют другой CRTs, различные версии STL, другую семантику броска исключения, различная оптимизация... Вы возглавляете вниз путь к безумию.

5
ответ дан 4 December 2019 в 08:02
поделиться

Одним путем Вы смогли организовывать код, должен использовать классы и в приложении и в dll, но сохранить интерфейс между двумя как экстерн "C" функции. Это - способ, которым я сделал это с C++ dlls используемый блоками C#. Экспортируемые функции DLL используются для управления экземплярами, доступными через статический класс* Экземпляр () методы как это:

__declspec(dllexport) void PrintSomething()
{
    (A::Instance())->PrintSometing();
}

Для нескольких объектов-экземпляров имейте функцию dll, создают экземпляр и возвращают идентификатор, который может затем быть передан Экземпляру () метод для использования необходимого конкретного объекта. Если Вы нуждаетесь в наследовании между приложением и dll, создаете класс на стороне приложения, которая переносит экспортируемые функции dll, и получите свои другие классы из этого. Организация Вашего кода как это сохранит интерфейс DLL простым и портативным и между компиляторами и между языками.

4
ответ дан 4 December 2019 в 08:02
поделиться

Я думаю, что Вы найдете эту статью MSDN полезной

Так или иначе, от быстрого взгляда на Ваш код, я могу сказать Вам, что Вы не должны объявлять виртуальный деструктор в интерфейсе. Вместо этого необходимо сделать delete this в A:: Выпуск (), когда касательно количества опускается до нуля.

3
ответ дан 4 December 2019 в 08:02
поделиться

Вы можете, пока Вы только используете extern "C" функции.

Это вызвано тем, что "C" ABI четко определен, в то время как ABI C++ сознательно не определяется. Таким образом каждому компилятору позволяют определить его собственное.

В некоторых компиляторах ABI C++ между различными версиями компилятора или даже с различными флагами генерирует несовместимый ABI.

3
ответ дан 4 December 2019 в 08:02
поделиться

Вы действительно критически зависите от v-сервировки, являющейся совместимым между VC и GCC. Это, несколько вероятно, будет хорошо. Обеспечение, что соглашение о вызовах соответствует, является чем-то, что необходимо проверить (COM: __ stdcall, Вы: __ thiscall).

Значительно, Вы получаете AV на записи. Ничто не пишется при создании самого вызова метода таким образом, вероятно, что оператор <<делает взрыв. Делает станд.:: суд, вероятно, инициализируется временем выполнения GCC, когда DLL загружается LoadLibrary ()? Отладчик должен сказать.

2
ответ дан 4 December 2019 в 08:02
поделиться

интересный.. что происходит, если Вы компилируете dll в VC ++ также, и что при помещении некоторых операторов отладки в CreateClass ()?

Я сказал бы, что его возможное, что Ваши 2 различных 'версии' во время выполнения суда конфликтуют вместо Вашего вызова метода - но я полагаю, что возвращенный указатель функции/dllclass не является 0x00000004?

0
ответ дан 4 December 2019 в 08:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: