Здравствуйте, AndyCyborg, Вы писали:

Я с проблемами с ADO не сталкивался, поэтому и не сразу написал.

Итак, IDL файл необходим для определения интерфейсов, что следует из аббревиатуры. Однако он сам используется редко, чаще используется его бинарный эквивалент в виде TLB файла. А также он может быть использован для генерации кода прокси/стаб DLLки.

Дело немного осложняется тем, что раньше до IDL файла был ODL файл, имеющий немного другой смысл и трактовку, но который наложил отпечаток на разбор IDL файла: ODL файл имел блок [library], в котором описывались интерфейсы всех объектов. Эти интерфейсы были дисп-интерфейсами и не требовали кодов маршаллинга, ибо использовался стандартный маршаллер по TLB файлу.

IDL файл стал расширением ODL, поэтому, наверное, и решили, что интерфейсы внутри блок [library] не требуют маршаллинга, в то время как вне его требуют. MSDN говорит об этом в "Generating a Type Library with MIDL" и "Generating a Proxy DLL and a Type Library from a Single IDL File" (ODL и IDL можно считать синонимами в этом контексте).

1. Итак, первое решение:
library XXXLib {
...
importlib("x:\program files\common files\system\ado\msado15.dll");  // определение _Recordset
...
interface Ixxx : IDispatch {
...
    [id(2),helpstring("method upload")] HRESULT upload([in] _Recordset* rs);

Для интерфейса Ixxx не будет генерится коды custom маршаллинга и, следовательно, нужно использовать только TLB маршаллер. Т.е. интерфейс должен быть OLE совестимым и иметь атрибут oleautomation.

2. Если нужна своя прокси DLL, то это решение не подходит. Нужно выносить определения интерфейсов вовне блока [library]:
interface Ixxx : IDispatch {
...
    [id(2),helpstring("method upload")] HRESULT upload([in] _Recordset* rs);
...
library XXXLib {
...
importlib("x:\program files\common files\system\ado\msado15.dll");  // определение _Recordset
...
interface Ixxx; // или как-то еще...

Однако это не компилится, потому что, как я раньше писал, MIDL имеет в этом месте проблему — _Recordset в месте определения интерфейса Ixxx еще не определен.

3. Можно было бы обойти через forward declaration интерфейса _Recordset
interface _Recordset; // forward declaration
interface Ixxx : IDispatch {
...
    [id(2),helpstring("method upload")] HRESULT upload([in] _Recordset* rs);
...
library XXXLib {
...
importlib("x:\program files\common files\system\ado\msado15.dll");  // определение _Recordset
...
interface Ixxx; // или как-то еще...

Однако это также не проходит, потому что _Recordset должен принадлежать текущему файлу (или по другой причине). Может быть пройдет вариант точного описания типа ADODB._Recordset, но у меня это не прошло.

4. Нужно искать вариант замены forward declaration. Для твоего случая есть файл msado15.idl, который мы и импортируем для определения интерфейсов. Если такого idlа нет, то нужно к следующему шагу перейти.
import "msado15.idl"; // определение _Recordset
interface Ixxx : IDispatch {
...
    [id(2),helpstring("method upload")] HRESULT upload([in] _Recordset* rs);
...
library XXXLib {
...
importlib("x:\program files\common files\system\ado\msado15.dll");  // определение _Recordset
...
interface Ixxx; // или как-то еще...

Все бы хорошо, но директива import генерит в h файле строчку #include "msado15.h", которая приводит к ошибке работы компилятора всего проекта, потому что MS не предоставила этот файл для своих пользователей.

5. Итак, создаем свой IDL файл, для которого создадим пресловутый h файл, который и позволит компиляцию проекта. В нем можно использовать конструкции, которые определяют интерфейсы _Recordset и другие. Или вставить директиву #import "msado15.dll" no_namespace // Correct place to import ADO.
Автор: Vi2    Оценить