2012-01-25 3 views
1

Я разрабатываю проект ATL. Некоторые интерфейсы содержат аргументы для передачи различных указателей. Вот мой IDL файл:Как объявить аргументы типа void * в IDL

import "oaidl.idl"; 
import "ocidl.idl"; 
[ 
    object, 
    uuid(618E64F5-676B-4A13-A513-DE3D4097294A), 
    dual, 
    nonextensible, 
    helpstring("IMyObject Interface"), 
    pointer_default(unique) 
] 
interface IMyObject : IDispatch{ 
    [id(1), helpstring("method Make")] HRESULT Make(DWORD type, LPVOID settings); 
    [id(2), helpstring("method Deserialize")] HRESULT Deserialize(LPVOID dataPtr, DWORD dataSize); 
}; 
[ 
    uuid(E57065B4-498F-4347-9ACC-A2C86A771720), 
    version(1.0), 
    helpstring("TestComVoid 1.0 Type Library") 
] 
library TestComVoidLib 
{ 
    importlib("stdole2.tlb"); 
    [ 
     uuid(1DC2528B-EA49-4F89-BB56-B1D667379644), 
     helpstring("MyObject Class") 
    ] 
    coclass MyObject 
    { 
     [default] interface IMyObject; 
    }; 
}; 

Первый метод IMyObject строит объект на основе типа и соответствующей структуры. Второй метод создает объект на основе двоичных данных.

Но я получаю ошибку MIDL2139: тип параметра не может извлечь из пустоты или недействительными *

Кроме того, я хочу сделать C# обертку с аргументами IntPtr передавать указатели. («Добавить ссылку» -> COM -> «TestComVoid 1.0 Type Library»)

Я попытался использовать INT_PTR вместо LPVOID, тогда я получаю int вместо IntPtr. Я пытался использовать DWORD_PTR вместо LPVOID, тогда я получаю uint вместо IntPtr. Я пытался использовать VARIANT вместо LPVOID, тогда я получаю Object вместо IntPtr.

Как правильно передать указатели на эти случаи?

+0

Пустота * не совместима с системой автоматизации. У вас есть *, чтобы передать что-то безопасное. Как SAFEARRAY (BYTE). –

+0

Ханс, спасибо за ответ. Но если используется тип SAFEARRAY, tlbimp генерирует тип System.Array. Мне нужен IntPtr. Что такое «Автоматизация совместима»? – vpp

+1

Автоматизация - это подмножество COM, его основной интерфейс - IDispatch. Тот, который вы используете. Это самый совместимый способ, позволяющий различным языкам и среде выполнения использовать код друг друга. Цена заключается в том, что у вас ограниченный набор типов для работы. Нет void * или IntPtr. –

ответ

3

Я нашел решение. Для этих методов необходимо использовать атрибут local. Вот оно:

[ 
    object, 
    uuid(618E64F5-676B-4A13-A513-DE3D4097294A), 
    dual, 
    nonextensible, 
    helpstring("IMyObject Interface"), 
    pointer_default(unique) 
] 
interface IMyObject : IDispatch{ 
    [id(1), helpstring("method Make"), local] HRESULT Make(DWORD type, LPVOID settings); 
    [id(2), helpstring("method Deserialize"), local] HRESULT Deserialize(LPVOID dataPtr, DWORD dataSize); 
}; 
0

Вы получили int вместо IntPtr, потому что INT_PTR действительно определяется как "int". Это означает, что "int size pointer" - не указатель на int.

Просто используйте LPDWORD (LPINT) вместо INT_PTR.

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