Я «немного» в шоке, после того, как попробовал создать DLL с управляемым кодом (.NET) для обычных приложений с «неуправляемым» кодом.
То, что для простых задач это работает легко (unmanaged в managed и наоборот) не обсуждается. Статьи есть на MSDN, да и сам делал - «Hello world» легко печатается из экспортируемой функции DLL с управляемым кодом. Но вот, когда я попросил NET использовать соглашение __stdcall в экпортируемых функциях, то компилятор выдал предупреждение, что моя просьба проигнорирована - __stdcall заменён модификатором __clrcall. Это может быть важным ( возможно не только для меня ) , если потребуется создать классы-обёртки для использования в неуправляемом коде управляемого кода DLL.
Например, есть декларация «интерфейсов» неких объектов, пусть, для работы с СУБД. Эти объекты расположены в DLL. Спецификация методов интерфейсов объектов, положим, в файле publicdbinterface.h:
В этом коде консольного приложения и коде DLL нет ничего, что касалось бы managed. Но, положим, захотелось сделать так, чтобы «обернуть» классы ADO.NET для работы с СУБД и «расширить» указанную выше DLL. Если попытаться пойти проторенной дорожной (как для обычных DLL), и попробовать создать в managed-DLL класс, типа того, что ниже – это будет крах:
Это не компилируется, поскольку нельзя в неуправляемом коде (класс CI_ADONETdb, см. выше) использовать ссылки на объекты классов, которые работают только под CLR (указатель OleDbConnection* Database, см. выше).
Положение можно «подправить», сделав код класса CI_ADONETdb управляемым:
public __gc class CI_ADONETdb: public IDatabaseInterface
{
private:
OleDbConnection* Database;
…
…
};
Но при этом «просто так» снова не получится. Компилятор выдаст ошибку – нельзя managed классы наследовать от unmanaged. Поэтому придётся переписать и интерфейсы IDatabaseInterface и IUnknownInterface, чтобы сделать их managed тоже.
Т.е. то, что было написано выше относительно «чисто абстрактных» классов IDatabaseInterface и IUnknownInterface теперь придётся изменить на следующее:
public __gc class IUnknownInterface
{
virtual HRESULT __stdcall QueryInterface(LPCTSTR int_type, void **ppv)
…
…
};
public __gc class IDatabaseInterface : public IUnknownInterface
{
virtual HRESULT __stdcall Open (void) = 0;
…
…
};
Результат таков – копилируется. При этом компилятор сообщает о предупреждении - warning C4440: calling convention redefinition from '__clrcall ' to '__stdcall ' ignored.
То, что компилируется – не большое утешение. Я уже не могу использовать эту DLL в своих проектах из–за ignored '__clrcall ' to '__stdcall '. Несмотря на то, что DLL компилируется, даже пробовать использовать её не стоит.
Как мне быть? Как «обернуть» объекты типа OleDbConnection так, чтобы сохранить соглашения __stdcall, указанные в начале моего поста?