Я бы не назвал это идеалом. Эгоистично и недальновидно создавать DLL, которая требует от своих потребителей использования того же компилятора, что и используемая DLL. (Расположение классов определяется реализацией, и поскольку оба модуля должны иметь одно и то же представление о том, что такое класс, они должны использовать один и тот же компилятор.)
Теперь, это не значит, что другие потребители DLL не могут подделать это. Им будет не так просто, как задумал разработчик DLL.
Когда вы говорите, что обратный вызов реализован через интерфейс, вы имеете в виду интерфейс в стиле COM, где класс C ++ имеет только чистые виртуальные методы, включая AddRef
, Release
и QueryInterface
, и они все используют stdcall соглашение о вызовах? Если это так, то вы можете просто написать класс Delphi, который реализует тот же интерфейс. Есть много примеров этого в исходном коде Delphi и другой литературе.
Если вы имеете в виду, что у вас не-COM-интерфейс, где класс C ++ имеет только чисто виртуальные методы, но не три COM-функции, то вы можете написать класс Delphi с той же компоновкой. Дублируйте порядок методов и убедитесь, что все методы являются виртуальными. Delphi VMT имеет ту же компоновку, что и большинство V ++ таблиц C ++ в реализациях Windows, по крайней мере, в том, что касается порядка указателей на функции. (В Delphi VMT также есть много данных, не относящихся к методам, но это не влияет на адреса методов.) Просто убедитесь, что вы поддерживаете четкие границы владения. DLL никогда не должна пытаться уничтожить объект; у него не будет C ++ - вызываемого деструктора, который может вызывать оператор delete
.
Если вы имеете в виду, что у вас есть произвольный класс C ++, который может включать члены данных, конструкторы или неочищенные методы, тогда ваша задача значительно сложнее. Следите, если это так; в противном случае я бы предпочел не заниматься этим прямо сейчас.
В целом, я повторю совет Мэйсона, что DLL должна использовать простые функции обратного вызова в стиле C. Хорошее практическое правило заключается в том, что если вы будете придерживаться техник, которые вы видите в Windows API, все будет в порядке. Если вы не контролируете, как взаимодействовать с DLL, пусть будет так. Но если вы можете сделать внешний интерфейс DLL более похожим на C, это было бы лучше. И это не значит, что вам нужно отказаться от интерфейса в стиле C ++; Вы могли бы предоставить два интерфейса, где интерфейс в стиле C служит оболочкой для вашего уже работающего интерфейса в стиле C ++.