Inquiridor
Problema com Interface COM em C#

Pergunta
-
Olá,
preciso declarar uma interface COM em C#, mas estou tendo problemas. Esta interface possui 2 métodos, um GetValue e um SetValue. Cada um deles recebe um GUID para identificar a propriedade desejada, e o outro é um objeto para receber ou enviar o valor.
Esta interface funciona perfeitamente em C++, e é declarada da seguinte forma:
interface IAVerCustomControl
{
STDMETHOD(SetValue) (THIS_ const GUID* Property, void* pValue) PURE;
STDMETHOD(GetValue) (THIS_ const GUID* Property, void* pValue) PURE;
};E há a declaração do GUID da mesma para o QueryInterface:
DEFINE_PROP_GUID(IID_IAVerCustomControl,
0x8998bb49, 0x2ff4, 0x4106, 0x95, 0x3c, 0x6d, 0xca, 0xbc, 0x7d, 0x95, 0x7b);Tentei declarar da seguinte forma em c#:
[ComImport]
[SuppressUnmanagedCodeSecurityAttribute]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8998BB49-2FF4-4106-953C-6DCABC7D957B")]
public interface IAVerCustomControl
{
[PreserveSig]
int SetValue(ref Guid Property, out object pValue);
[PreserveSig]
int GetValue(ref Guid Property, out object pValue);
}Se passo um GUID inválido, o HRESULT retorna erro, mas passando um válido ele retorna null no object para o GetValue e retorna erro genérico (E_FAIL) para o SetValue. Jpa tentei modificar alguns atributos, mas sem sucesso.
Obrigado.
Todas as Respostas
-
-
Estou alterando um projeto C# já existente, vou adicionar um filtro directshow do SDK da AverMedia (não implementada por mim) e preciso acessar a interface customizada que descrevi. Para utilizá-la com C++, a declaração é a que havia passado:
interface IAVerCustomControl
{
STDMETHOD(SetValue) (THIS_ const GUID* Property, void* pValue) PURE;
STDMETHOD(GetValue) (THIS_ const GUID* Property, void* pValue) PURE;
};
Esta interface funciona sem problemas. No entanto, como o projeto está em C#, procurei declará-la da seguinte forma:
[ComImport]
[SuppressUnmanagedCodeSecurityAttribute]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8998BB49-2FF4-4106-953C-6DCABC7D957B")]
public interface IAVerCustomControl
{
[PreserveSig]
int SetValue(ref Guid Property, out object pValue);
[PreserveSig]
int GetValue(ref Guid Property, out object pValue);
}
No entanto, desta forma não está funcionando. O método SetValue sempre altera o valor da variável pValue para null, e o GetValue resulta em erro desconhecido. Já tentei modificar os atributos da interface de várias formas, mas não resolveram. Também já tentei adicionar os atributos para interpretação dos parâmetros, como [MarshalAs(UnmanagedType.IUnknown)] para o pValue, mas sem sucesso.Agradeço a atenção.
-
-
Não, esta interface IAVerCustomControl não foi implementada por mim, faz parte do SDK da AverMedia.
Em C++, para utilizar a inteface para, por exemplo, alterar a propriedade noise reduction:
IAVerCustomControl *piCustomControl = NULL;
hr = pVideoProc->QueryInterface(IID_IAVerCustomControl,(void**)&piCustomControl);
BOOL bEnableNR = FALSE;
piCustomControl->SetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);
piCustomControl->GetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);Em C#, estou fazendo da seguinte forma:
IAVerCustomControl iAcc = (IAVerCustomControl)pAverVideoProcessor;
Guid Guid_AVerNoiseReductionMode = new Guid(0x1ed9c780, 0x3272, 0x4a11, 0x8d, 0xdb, 0x2d, 0x9c, 0x79, 0xb9, 0x8c, 0x1c);
object nrEnabled = true;
hr = iAcc.GetValue(ref Guid_AVerNoiseReductionMode, out nrEnabled);
hr = iAcc.SetValue(ref Guid_AVerNoiseReductionMode, out nrEnabled);Também já tentei utilizar o nrEnabled como bool, mas não resolveu.
- Editado Apek_Dev segunda-feira, 2 de dezembro de 2013 13:47
-
Não, esta interface IAVerCustomControl não foi implementada por mim, faz parte do SDK da AverMedia.
Em C++, para utilizar a inteface para, por exemplo, alterar a propriedade noise reduction:
IAVerCustomControl *piCustomControl = NULL;
hr = pVideoProc->QueryInterface(IID_IAVerCustomControl,(void**)&piCustomControl);
BOOL bEnableNR = FALSE;
piCustomControl->SetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);
piCustomControl->GetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);Em C#, estou fazendo da seguinte forma:
IAVerCustomControl iAcc = (IAVerCustomControl)pAverVideoProcessor;
Guid Guid_AVerNoiseReductionMode = new Guid(0x1ed9c780, 0x3272, 0x4a11, 0x8d, 0xdb, 0x2d, 0x9c, 0x79, 0xb9, 0x8c, 0x1c);
object nrEnabled = true;
hr = iAcc.GetValue(ref Guid_AVerNoiseReductionMode, ref nrEnabled);
hr = iAcc.SetValue(ref Guid_AVerNoiseReductionMode, ref nrEnabled);Também já tentei utilizar o nrEnabled como bool, mas não resolveu.
Essa linha
IAVerCustomControl iAcc = (IAVerCustomControl)pAverVideoProcessor;
Tire ficando assim
IAVerCustomControl iAcc = pAverVideoProcessor;
Por favor e teste
-
O pAverVideoProcessor é um IBaseFilter, não é possível converter implicitamente na interface IAverCustomControl.
Quando utilizo o cast, a lib do DirectShow utiliza o médoto QueryInterface (a lib não disponibiliza o médoto diretamente, somente através do cast), retornando o objeto COM. No entanto, os métodos que não funcionam. Já conferi o GUID utilizado na interface e está ok.
-
-
Desculpe, não entendi bem sua pergunta. O pAverVideoProcessor é uma instância do tipo IBaseFilter (do DirectShow), criada a partir do "Filter Moniker" do filtro "AVerMedia Video Processor (capsdk)", que implementa esta interface que estou querendo utilizar.
Para criar esta IBaseFilter através do Filter Moniker, estou utilizando o método abaixo:
public static object CreateObject(string displayName)
{
int hr = 0;
object obj = null;
IBindCtx bindCtx = null;
IMoniker moniker = null;
try
{
hr = CreateBindCtx(0, out bindCtx);
Marshal.ThrowExceptionForHR(hr);
int eaten;
hr = MkParseDisplayName(bindCtx, displayName, out eaten, out moniker);
Marshal.ThrowExceptionForHR(hr);
Guid guid = typeof(IBaseFilter).GUID;
moniker.BindToObject(bindCtx, null, ref guid, out obj);
}
finally
{
if (bindCtx != null) Marshal.ReleaseComObject(bindCtx);
if (moniker != null) Marshal.ReleaseComObject(moniker);
}
return obj;
} -
Faz esse teste então naquele antigo código:
é porque amigo Interface C++ é muito diferente de C#
mas, vamos tentar por erros:
coloque dinâmico assim
var iAcc = (IAVerCustomControl)pAverVideoProcessor;
Tente rodar para ver se ele roda!!!
Eu to tentanndo mas, eu já mexi e nunca passei por isso!
-
Fiz o teste, mas ocorre o mesmo problema.
Acho estranho que, apesar das interfaces serem diferentes em C#, deve haver uma forma de fazê-la funcionar. Por isto mencionei anteriormente que deve estar faltando algum atributo para utilização correta do objeto COM.
Já verifiquei as interfaces que são declaradas na lib do DirectShow e não encontrei nada diferente. Como também não desenvolvi o filtro, não imagino o que possa resolver.
Obrigado.
-
- Editado Fulvio Cezar Canducci Dias segunda-feira, 2 de dezembro de 2013 18:28
-
Sim. Eu crio o filtro "AVerMedia Video Processor" como um IBase filter e adiciono ao graph, funciona sem problemas. Quando faço o cast (QueryInterface) para a interface IAVerCustomControl, é retornado um objeto COM (o que entendo que está então encontrando a interface com a GUID informada). O que não funciona corretamente é a chamada aos métodos mesmo.
Tentei recriar a mesma definição da interface utilizada no C++, ficando desta forma:
[ComImport]
[SuppressUnmanagedCodeSecurityAttribute]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("8998BB49-2FF4-4106-953C-6DCABC7D957B")]
public interface IAVerCustomControl
{
[PreserveSig]
unsafe int SetValue([In] Guid* Property, [In] void* pValue);
[PreserveSig]
unsafe int GetValue([In] Guid* Property, [Out] void* pValue);
}Testei utilizando da seguinte forma:
var iAcc = (IAVerCustomControl)pAverVideoProcessor;
Guid Guid_AVerNoiseReductionMode = new Guid(0x1ed9c780, 0x3272, 0x4a11, 0x8d, 0xdb, 0x2d, 0x9c, 0x79, 0xb9, 0x8c, 0x1c);
bool isEnabled = true;
unsafe
{
bool* nrEnabled = &isEnabled;
//hr = iAcc.GetValue(&Guid_AVerNoiseReductionMode, &nrEnabled);
hr = iAcc.SetValue(&Guid_AVerNoiseReductionMode, &nrEnabled);
}No entanto, ocorre um efeito similar. Ao chamar o GetValue, o endereço do ponteiro nrEnabled é zerado. Se, ao invés de chamar GetValue, chamar SetValue, um erro não especificado é retornado.