Опитвам се да преобразувам следните два интерфейса от C заглавен файл в Delphi PAS единица, но се натъкнах на странни проблеми, когато използвах тези, които направих сам. Имам нужда от помощ, за да разбера как да ги внедря в Delphi.
Изходни интерфейси от c заглавен файл:
interface IParamConfig: IUnknown
{
HRESULT SetValue([in] const VARIANT* pValue, [in] BOOL bSetAndCommit);
HRESULT GetValue([out] VARIANT* pValue, [in] BOOL bGetCommitted);
HRESULT SetVisible(BOOL bVisible);
HRESULT GetVisible(BOOL* bVisible);
HRESULT GetParamID(GUID* pParamID);
HRESULT GetName([out] BSTR* pName);
HRESULT GetReadOnly(BOOL* bReadOnly);
HRESULT GetFullInfo([out] VARIANT* pValue, [out] BSTR* pMeaning, [out] BSTR* pName, [out] BOOL* bReadOnly, [out] BOOL* pVisible);
HRESULT GetDefValue([out] VARIANT* pValue);
HRESULT GetValidRange([out] VARIANT* pMinValue, [out] VARIANT* pMaxValue, [out] VARIANT* pDelta);
HRESULT EnumValidValues([in][out] long* pNumValidValues, [in][out] VARIANT* pValidValues,[in][out] BSTR* pValueNames);
HRESULT ValueToMeaning([in] const VARIANT* pValue, [out] BSTR* pMeaning);
HRESULT MeaningToValue([in] const BSTR pMeaning, [out] VARIANT* pValue);
}
interface IModuleConfig: IPersistStream
{
HRESULT SetValue([in] const GUID* pParamID, [in] const VARIANT* pValue);
HRESULT GetValue([in] const GUID* pParamID, [out] VARIANT* pValue);
HRESULT GetParamConfig([in] const GUID* pParamID, [out] IParamConfig** pValue);
HRESULT IsSupported([in] const GUID* pParamID);
HRESULT SetDefState();
HRESULT EnumParams([in][out] long* pNumParams, [in][out] GUID* pParamIDs);
HRESULT CommitChanges([out] VARIANT* pReason);
HRESULT DeclineChanges();
HRESULT SaveToRegistry([in] HKEY hKeyRoot, [in] const BSTR pszKeyName, [in] const BOOL bPreferReadable);
HRESULT LoadFromRegistry([in] HKEY hKeyRoot, [in] const BSTR pszKeyName, [in] const BOOL bPreferReadable);
HRESULT RegisterForNotifies([in] IModuleCallback* pModuleCallback);
HRESULT UnregisterFromNotifies([in] IModuleCallback* pModuleCallback);
}
Това е „най-доброто ми усилие“ досега:
type
TWideStringArray = array[0..1024] of WideString;
TOleVariantArray = array[0..1024] of OleVariant;
TGUIDArray = array[0..1024] of TGUID;
IParamConfig = interface(IUnknown)
['{486F726E-5043-49B9-8A0C-C22A2B0524E8}']
function SetValue(const pValue: OleVariant; bSetAndCommit: BOOL): HRESULT; stdcall;
function GetValue(out pValue: OleVariant; bGetCommitted: BOOL): HRESULT; stdcall;
function SetVisible(bVisible: BOOL): HRESULT; stdcall;
function GetVisible(bVisible: BOOL): HRESULT; stdcall;
function GetParamID(pParamID: PGUID): HRESULT; stdcall;
function GetName(out pName: WideString): HRESULT; stdcall;
function GetReadOnly(bReadOnly: BOOL): HRESULT; stdcall;
function GetFullInfo(out pValue: OleVariant; out pMeaning: WideString; out pName: WideString; out pReadOnly: BOOL; out pVisible: BOOL): HRESULT; stdcall;
function GetDefValue(out pValue: OleVariant): HRESULT; stdcall;
function GetValidRange(out pMinValue: OleVariant; out pMaxValue: OleVariant; out pDelta: OleVariant): HRESULT; stdcall;
function EnumValidValues(var pNumValidValues: Integer; var pValidValues: TOleVariantArray; var pValueNames: TWideStringArray): HRESULT; stdcall;
function ValueToMeading(const pValue: OleVariant; out pMeaning: WideString): HRESULT; stdcall;
function MeaningToValue(const pMeaning: WideString; out pValue: OleVariant): HRESULT; stdcall;
end;
IModuleConfig = interface(IPersistStream)
['{486F726E-4D43-49B9-8A0C-C22A2B0524E8}']
function SetValue(const pParamID: TGUID; const pValue: OleVariant): HRESULT; stdcall;
function GetValue(const pParamID: TGUID; out pValue: OleVariant): HRESULT; stdcall;
function GetParamConfig(const ParamID: TGUID; out pValue: IParamConfig): HRESULT; stdcall;
function IsSupported(const pParamID: TGUID): HRESULT; stdcall;
function SetDefState: HRESULT; stdcall;
function EnumParams(var pNumParams: Integer; var pParamIDs: TGUIDArray): HRESULT; stdcall;
function CommitChanges(out pReason: OleVariant): HRESULT; stdcall;
function DeclineChanges: HRESULT; stdcall;
function SaveToRegistry(hKeyRoot: HKEY; const pszKeyName: WideString; const bPreferReadable: BOOL): HRESULT; stdcall;
function LoadFromRegistry(hKeyRoot: HKEY; const pszKeyName: WideString; const bPreferReadable: BOOL): HRESULT; stdcall;
function RegisterForNotifies(pModuleCallback: IModuleCallback): HRESULT; stdcall;
function UnregisterFromNotifies(pModuleCallback: IModuleCallback): HRESULT; stdcall;
end;
Ето примерен код, който използва филтъра DirectShow и се опитва да използва както интерфейсите IModuleConfig, така и IParamConfig на този обект:
procedure TForm10.Button1Click(Sender: TObject);
const
CLSID_VideoDecoder: TGUID = '{C274FA78-1F05-4EBB-85A7-F89363B9B3EA}';
var
HR: HRESULT;
Intf: IUnknown;
NumParams: Long;
I: Integer;
ParamConfig: IParamConfig;
ParamName: WideString;
Value: OleVariant;
ValAsString: String;
Params: TGUIDArray;
begin
CoInitializeEx(nil, COINIT_MULTITHREADED);
try
HR := CoCreateInstance(CLSID_VideoDecoder, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Intf);
if Succeeded(HR) then
begin
FVideoDecoder := Intf as IBaseFilter;
if Supports(FVideoDecoder, IID_IModuleConfig) then
begin
HR := (FVideoDecoder as IModuleConfig).EnumParams(NumParams, Params);
if HR = S_OK then
begin
for I := 0 to NumParams - 1 do
begin
HR := (FVideoDecoder as IModuleConfig).GetParamConfig(Params[I], ParamConfig);
if HR = S_OK then
begin
try
ParamConfig.GetName(ParamName);
ParamConfig.GetValue(Value, True);
try
ValAsString := VarToStrDef(Value, 'Error');
SL.Add(String(ParamName) + '=' + String(ValAsString)); // <-- ADDING THIS LINE WILL ALWAYS MAKE EnumParams call return S_FALSE = 1
except
end;
finally
ParamConfig := nil;
end;
end;
end;
end;
end;
end;
finally
CoUninitialize;
end;
end;
С помощта на програмата за отстраняване на грешки виждам, че примерният код извлича данни както за променливите ParamName, така и за стойността, но когато се опитам да включа код, за да ги съхраня в списъка с низове (SL), извикването на EnumParams винаги ще връща S_FALSE (1), а не S_OK (0). Ако коментирам реда SL.Add(...) и RECOMPILE, той ще работи отново. Ако го включа отново и РЕКОМПИЛИРАМ, няма да стане. Това ме кара да вярвам, че нещо обърква паметта в даден момент поради моята неправилна реализация на тези интерфейси и включването на допълнителния код го прави.
Почти съм сигурен, че типовете, които съм присвоил на променливите, са по някакъв начин виновникът за това, особено вторият параметър на EnumParams, който трябва да върне масив от GUID*. Също така съм много несигурен относно извикването IParamConfig.EnumValidValues, което също връща масиви от стойности.
Използвам Delphi XE2.
Всяка помощ по този въпрос е много ценена.