Есть набор классов, связанных между собой COM-образным способом. Т.е. все наследуются от IUnknown и содержат в себе виртуальную QueryInterface(GUID* id, void** ppInterface).
Также есть статические factory-функции, создающие определенный класс: CreateSomeClass(void** ppClass).
Каким образом можно использовать эти функции и классы в C#? Я описал интерфейсы в C#-модуле, обозвал factory-функии в C-модуле как экспортируемые, но не могу понять, как написать в C# конструкции вида "void**". Пусть будет не void, а object или IUnknown, неважно. Что нужно написать вместо двойного указателя?
Здравствуйте, Starlight, Вы писали:
S>Есть набор классов, связанных между собой COM-образным способом. Т.е. все наследуются от IUnknown и содержат в себе виртуальную QueryInterface(GUID* id, void** ppInterface). S>Также есть статические factory-функции, создающие определенный класс: CreateSomeClass(void** ppClass). S>Каким образом можно использовать эти функции и классы в C#? Я описал интерфейсы в C#-модуле, обозвал factory-функии в C-модуле как экспортируемые, но не могу понять, как написать в C# конструкции вида "void**". Пусть будет не void, а object или IUnknown, неважно. Что нужно написать вместо двойного указателя?
extern static void CreateSomeClass( out object ppClass );
В>>extern static void CreateSomeClass( out object ppClass );
В>>
В>>Вроде так
M>А если более "человечно", то:
В>>
В>>extern static object CreateSomeClass();
В>>
M>Хотя это и меньше похоже на оригинал, но более принятый вид.
В том-то и дело, что должно быть очень "похоже" на оригинал
Допустим, что нет возможности переделать исходные C-коды. Можно ли использовать в этом случае "out object" вместо "void**"?
Кстати, поясните, пожалуйста, а чем отличается "out object" от "ref object"?
S>В том-то и дело, что должно быть очень "похоже" на оригинал S>Допустим, что нет возможности переделать исходные C-коды. Можно ли использовать в этом случае "out object" вместо "void**"?
Да.
Стоит посмотреть в MSDN описание DllImportAttribute и MarshalAsAttribute. Конкретно, параметру out object нужно приставить атрибут, что это будет не VARIANT, а указатель. По умолчанию out object рассматривается в интеропе как вариант.
S>Кстати, поясните, пожалуйста, а чем отличается "out object" от "ref object"?
В параметр ref нужно будет передавать инициализированное значение, а в out — не обязательно. В данном случае других различий нет.
Здравствуйте, mihailik, Вы писали:
S>>В том-то и дело, что должно быть очень "похоже" на оригинал S>>Допустим, что нет возможности переделать исходные C-коды. Можно ли использовать в этом случае "out object" вместо "void**"?
M>Да. M>Стоит посмотреть в MSDN описание DllImportAttribute и MarshalAsAttribute. Конкретно, параметру out object нужно приставить атрибут, что это будет не VARIANT, а указатель. По умолчанию out object рассматривается в интеропе как вариант.
Указатель в C#? Может я чего-то недопонимаю, но как это написать?
S>>Кстати, поясните, пожалуйста, а чем отличается "out object" от "ref object"?
M>В параметр ref нужно будет передавать инициализированное значение, а в out — не обязательно. В данном случае других различий нет.
Здравствуйте, desperado_gmbh, Вы писали:
В>>А так я не понимаю, как это может в случае DllImport
_>
_>[DllImport(..., PreserveSig = false)]
_>
И? Он тебе не даром про HRESULT сказал. Только HRESULT автоматом в исключение можно превратить, да и то если он стандартный или ассоциировано IErrorInfo.
... << RSDN@Home 1.1 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
( в смысле object CreateSomeClass( out object ppClass2 );
или
object CreateSomeClass( out object ppClass1 );
, есть некоторая путаница, правда?
)
По каким правилам выбирается параметр, который помещяется как возвращяемое значение? Я до сих пор считал, что для этого параметр должен быть помечен как retval. И здесь есть аналогия с VB, в котором параметро [out,retval] IUnknown** ppRet переходит в возвращяемое значение. Или я не прав?
И можно ли функция, описанную в IDL так
HRESULT Function( [out] IUknown** ppObject );
в С# декларировать как
object Function();
, не смотря на то что не поставлено retval?
Опять же есть два написания
void Function( IUnknown** ppObject );
как
void Function( ref object ppObject )
и
void Function( out object ppObject)
И если функция требует, что бы ей передавили валидный указатель, то будь любезен поставить ref а в таком варианте не может быть написания как object Function();
Здравствуйте, VladD2, Вы писали:
VD>И? Он тебе не даром про HRESULT сказал. Только HRESULT автоматом в исключение можно превратить, да и то если он стандартный или ассоциировано IErrorInfo.
Автору исходного сообщения это действительно не подходит — у него возвращается void. Я прояснил Ведмедю, что превращать HRESULT в Exception можно не только в методах интерфейсов.
Здравствуйте, desperado_gmbh, Вы писали:
_>Здравствуйте, VladD2, Вы писали:
VD>>И? Он тебе не даром про HRESULT сказал. Только HRESULT автоматом в исключение можно превратить, да и то если он стандартный или ассоциировано IErrorInfo.
_>Автору исходного сообщения это действительно не подходит — у него возвращается void. Я прояснил Ведмедю, что превращать HRESULT в Exception можно не только в методах интерфейсов.
Дык дело не в HRESULT, дело в возвращяемом параметре. в интерфейсах возвращяемый параметр помечается как
[out,retval], тогда как в статических функциях он никак не помечается. ПО каким правилам вычисляется тогда какой параметр сделать retval?
Здравствуйте, Ведмедь, Вы писали:
В>Дык дело не в HRESULT, дело в возвращяемом параметре. в интерфейсах возвращяемый параметр помечается как В>[out,retval], тогда как в статических функциях он никак не помечается. ПО каким правилам вычисляется тогда какой параметр сделать retval?
Я и сам не пойму. В роторе код обработки PreserveSig есть, но все очень запущено. Логично было бы предположить, что последний.