从 Delphi 中的 vidcap.h 调用 IKsTopologyInfo::CreateNodeInstance

发布于 2024-12-04 03:56:51 字数 2254 浏览 0 评论 0原文

我正在用 Delphi 编写一个管理网络摄像头的小应用程序。我有 C++ 中的工作示例代码,我需要在 Delphi 中重写它作为我的应用程序的一部分。在 Delphi 中,一切工作正常,除了单个方法调用,它崩溃并显示“模块‘vidcap.ax’中地址 63252469 处的访问冲突。写入地址 11D206FD”消息。

这是可以工作的 C++ 示例代码的一部分(没有错误处理):

#include <vidcap.h>         // For IKsTopologyInfo  
#include <ksproxy.h>        // For IKsControl  
....  
//pKsTopologyInfo is passed from the outside
IKsControl *pKsControl = NULL;  
DWORD dwNumNodes = 0;  
pKsTopologyInfo->get_NumNodes(&dwNumNodes);  
for(unsigned int i = 0; i < dwNumNodes; i++)  
{  
  pKsTopologyInfo->get_NodeType(i, &guidNodeType);  
  if(IsEqualGUID(guidNodeType, KSNODETYPE_DEV_SPECIFIC))  
  {  
    hr = pKsTopologyInfo->CreateNodeInstance(i, IID_IKsControl, (void **)&pKsControl);

这是我在 Delphi 中的代码的相应部分:

//KsTopologyInfo is IKsTopologyInfo passed from the outside  
//pKsControl is ^IKsControl, which is taken from DirectShow9.pas from DSPack components set.
KsTopologyInfo.get_NumNodes(@dwNumNodes);  
for i:=0 to dwNumNodes-1 do  
begin  
  KsTopologyInfo.get_NodeType(i,@guidNodeType);  
  if IsEqualGUID(guidNodeType,KSNODETYPE_DEV_SPECIFIC) then  
  begin  
    KsTopologyInfo.CreateNodeInstance(i,IID_IKsControl,@pKsControl);  

错误发生在 Delphi 代码的最后一行,而在 C++ 中则工作正常。< br> 逐步调试器期间的检查没有显示任何差异 - 在 Delphi 和 C++ 中,dwNumNodes 都为 11,然后当 i==3 且 guidNodeType=={941C7AC0-C559-11D0-8A2B-00A0C9255AC1} 时 IsEqualGUID 返回 TRUE。因此,在这两种情况下,它都会使用相同的值 i=3 和 IID_IKsControl={28F54685-06FD-11D2-B27A-00A0C9223196}

调用 CreateNodeInstance 遗憾的是,我找不到 vidcap.h 转换为 Delphi .pas 文件,所以我写了我自己对 IKsTopologyInfo 的描述,我想我在 CreateNodeInstance 方法描述中有错误。这是来自 vidcap.h:

virtual HRESULT STDMETHODCALLTYPE CreateNodeInstance(  
  /* [in] */ DWORD dwNodeId,  
  /* [in] */ REFIID iid,  
  /* [out] */ void **ppvObject) = 0;  

这是我的 Delphi 变体:

function CreateNodeInstance(dwNodeId:DWord; iid:TGuid; p:Pointer):HRESULT; stdcall;  

我使用第三个参数尝试了很多变体 - var Obj、Pointer、PPointer(即 ^Pointer),并且还尝试将不同的变体值传递给它(IKsControl、^IKsControl、^(^IKsControl)、Pointer、^Pointer - 但它们都不起作用。无论如何,我遇到了同样的错误。

需要有关如何使其工作以及如何工作的任何建议应该查看正确的 IKsTopologyInfo.CreateNodeInstance 描述并在 Delphi 中调用。

I'm writing a tiny app managing webcam in Delphi. I have working sample piece of code in C++, and i need to rewrite it in Delphi as a part of my app. All works fine in Delphi, except single method call, which crashes with "Access violation at address 63252469 in module 'vidcap.ax'. Write of address 11D206FD" message.

Here is a part of C++ sample code which works (without errors handling):

#include <vidcap.h>         // For IKsTopologyInfo  
#include <ksproxy.h>        // For IKsControl  
....  
//pKsTopologyInfo is passed from the outside
IKsControl *pKsControl = NULL;  
DWORD dwNumNodes = 0;  
pKsTopologyInfo->get_NumNodes(&dwNumNodes);  
for(unsigned int i = 0; i < dwNumNodes; i++)  
{  
  pKsTopologyInfo->get_NodeType(i, &guidNodeType);  
  if(IsEqualGUID(guidNodeType, KSNODETYPE_DEV_SPECIFIC))  
  {  
    hr = pKsTopologyInfo->CreateNodeInstance(i, IID_IKsControl, (void **)&pKsControl);

And here is a corresponding part of my code in Delphi:

//KsTopologyInfo is IKsTopologyInfo passed from the outside  
//pKsControl is ^IKsControl, which is taken from DirectShow9.pas from DSPack components set.
KsTopologyInfo.get_NumNodes(@dwNumNodes);  
for i:=0 to dwNumNodes-1 do  
begin  
  KsTopologyInfo.get_NodeType(i,@guidNodeType);  
  if IsEqualGUID(guidNodeType,KSNODETYPE_DEV_SPECIFIC) then  
  begin  
    KsTopologyInfo.CreateNodeInstance(i,IID_IKsControl,@pKsControl);  

The error occurs in the Delphi code at the last line here, while in the C++ it works fine.
Inspection during step-by-step debugger does not show any differences - both in Delphi and C++ it gets 11 for dwNumNodes, then IsEqualGUID returns TRUE when i==3 and guidNodeType=={941C7AC0-C559-11D0-8A2B-00A0C9255AC1}. So in both cases it calls CreateNodeInstance with the same values i=3 and IID_IKsControl={28F54685-06FD-11D2-B27A-00A0C9223196}

To my pity, i couldn't find vidcap.h transformed to Delphi .pas file, so i written my own description for IKsTopologyInfo, and i suppose that i have error in CreateNodeInstance method description. Here it is from vidcap.h:

virtual HRESULT STDMETHODCALLTYPE CreateNodeInstance(  
  /* [in] */ DWORD dwNodeId,  
  /* [in] */ REFIID iid,  
  /* [out] */ void **ppvObject) = 0;  

And here is my variant for Delphi:

function CreateNodeInstance(dwNodeId:DWord; iid:TGuid; p:Pointer):HRESULT; stdcall;  

I tried a lot of variants with the third parameter - var Obj, Pointer, PPointer (which is ^Pointer), and also tried to pass different variants values to it (IKsControl, ^IKsControl, ^(^IKsControl), Pointer, ^Pointer - and none of them work. In any case i got the same error.

Need any advice on how make it working, and how should look correct IKsTopologyInfo.CreateNodeInstance description and call in Delphi.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是有多爱你 2024-12-11 03:56:51

根据 MSDN REFIID 的定义

typedef GUID IID;
typedef IID* REFIID;

所以 REFIID 是一个指向 GUID 的指针,应该翻译为 PGUID 或者, iid 是一个输入参数,似乎是强制的,也可以作为 const TGUID 传递。

另外,MSDN 指出 CreateNodeInstance

ppvObject接收指向节点对象上请求的接口的指针。 调用者必须释放接口

所以第三个参数应该声明为一个接口的指针,以便允许Delphi管理它。将其声明为 var IUnknown 或者,因为它是输出参数,所以声明为 out IUnknown 强制该参数是 IUnknown 类型的变量,因此必须将其转换为真实的接口类型才能使用它。

C++ 声明

virtual HRESULT STDMETHODCALLTYPE CreateNodeInstance(  
  /* [in] */ DWORD dwNodeId,  
  /* [in] */ REFIID iid,  
  /* [out] */ void **ppvObject) = 0;

变为

function CreateNodeInstance(dwNodeId: DWord; const iid: TGUID; ppvObject: PUnknown): HRESULT; stdcall;

And 可以按如下方式调用:

var
  KsControl: IKsControl;

KsTopologyInfo.CreateNodeInstance(i, IID_IKsControl, @KsControl);

According to MSDN definition of REFIID:

typedef GUID IID;
typedef IID* REFIID;

So REFIID is a pointer to a GUID and should be translated as PGUID or, as iid is an input parameter and seems to be mandatory, can also be passed as a const TGUID.

Also, MSDN states that in CreateNodeInstance:

ppvObject receives a pointer to the requested interface on the node object. The caller must release the interface.

So the third parameter should be declared as a pointer to an interface in order to allow Delphi to manage it. Declaring it as a var IUnknown or, as it is an output parameter, as an out IUnknown forces the parameter to be a variable of type IUnknown and therefore that must be casted to the real interface type for using it.

The C++ declaration

virtual HRESULT STDMETHODCALLTYPE CreateNodeInstance(  
  /* [in] */ DWORD dwNodeId,  
  /* [in] */ REFIID iid,  
  /* [out] */ void **ppvObject) = 0;

becomes

function CreateNodeInstance(dwNodeId: DWord; const iid: TGUID; ppvObject: PUnknown): HRESULT; stdcall;

And can be called as follows:

var
  KsControl: IKsControl;

KsTopologyInfo.CreateNodeInstance(i, IID_IKsControl, @KsControl);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文