gpt4 book ai didi

c++ - 将经典 ASP VBScript 参数 ByRef 传递给 COM c++

转载 作者:行者123 更新时间:2023-11-30 02:13:05 25 4
gpt4 key购买 nike

这很简单。有一个 c++ 函数使用 ByRef 参数同时返回三个变量。

STDMETHODIMP CReportManager::GetReportAccessRights(long lReportCode, VARIANT_BOOL *bShared, VARIANT_BOOL *bRunOnly, VARIANT_BOOL *bCopy)

但是,调用 c++ 函数时,VBScript ASP 代码似乎没有获取 bShares、bRunOnly 和 bCopy 的新值。
dim bAllShared, bAllCopy, bAllRunOnly
bAllShared = true
bAllCopy = true
bAllRunOnly = true
m_oReportManager.GetReportAccessRights CLng(m_lRptCod), CBool(bAllShared), CBool(bAllRunOnly), CBool(bAllCopy)
'bAllShared always equals true

我能做些什么来解决这个问题吗?谁能解释为什么会这样?

最佳答案

有两个问题:

首先,您不能检索作为 [ref] 传回的值。来自 VBScript 的参数,除非它们的类型为 VARIANT在 C++ 代码中。

VBScript 使用一种称为 COM 自动化的后期绑定(bind)技术,它通过单个通用方法调用将每个方法调用路由到 COM 对象:IDISPATCH:Invoke(...) . (当您对变量 As Object 进行调暗并对其进行调用时,Visual Basic 使用相同的技术)
Invoke()接受一个字符串,它是您正在调用的方法的名称,以及一个参数数组(加上其他在这里不重要的东西)。

您的 C++ 对象不必担心它,因为 ATL 支持称为双接口(interface)的东西,它将为您完成所有令人讨厌的工作。当您的对象收到对 IDISPATCH:Invoke() 的调用时, ATL 将:

  • 查找请求的方法名称并在您的类中识别相应的方法(如果存在,否则将在 VBScript 中返回错误)。
  • 根据需要翻译来自 VARIANT 的任何输入参数(技术上 VARIANTARG ,几乎相同)根据方法的签名将它们对应的数据类型(如果它们与您的方法所期望的不匹配,则会抛出错误)
  • 调用您的GetReportAccessRights()方法,带有未打包的参数。

  • 当您的 GetReportAccessRights()方法返回,ATL 重新打包 [retval]参数转换为新的 VARIANT (技术上是 VARIANTARG )并将其返回给 VBScript。

    现在,你 可以回传 [ref]值,但它们 必须VARIANT s。 ATL 不会重新打包除 [retval] 之外的任何参数值。对你来说,所以你必须使用 VARIANT * 的类型对于任何 [ref]要返回给调用者的参数。当您这样做时,ATL 将保持参数不受干扰,而 VBScript 将正确接收它。

    为了使用变体,COM 头文件为我们提供了方便的宏和常量,我将在这里使用它们(VT_BOOL、V_VT()、V_BOOL()、FAILED()):
    // I usually initialize to Empty at the top of the method,
    // before anything can go wrong.
    VariantInit(bAllShared);
    // My bad -- ignore the above. It applies to [out] parameters only.
    // Because bAllShared is passed as a [ref] variable,
    // calling VariantInit() on them would leak any preexisting value.
    // Instead, read the incoming value from the variable (optional),
    // then "clear" them before storing new values (mandatory):

    // This API figures out what's in the variable and releases it if needed
    // * Do nothing on ints, bools, etc.
    // * Call pObj->Release() if an Object
    // * Call SysFreeString() if a BSTR
    // etc
    VariantClear(bAllShared);

    初始化它们;这将导致他们以前的值泄漏。

    阅读 VARIANT :
    // Always check that the value is of the proper type
    if (V_VT(bAllShared) == VT_BOOL ) {
    // good
    bool myArg = (V_BOOL(bAllShared) == VARIANT_TRUE);
    } else {
    // error, bad input
    }

    或者更好的是,您应该始终尝试转换自己,因为 VBScript 用户期望“True”和 1 的行为与 VARIANT_TRUE 相同。幸运的是,COM 有一个很棒的实用 API:
    // This is exactly the same thing that VBScript does internally
    // when you call CBool(...)
    VARIANT v;
    VariantInit(&v);
    if( FAILED(VariantChangeType(&v, &bAllShared, 0, VT_BOOL) )
    {
    // error, can't convert
    }
    bool myArg = (V_BOOL(v) == VARIANT_TRUE);

    写信给 VARIANT :
    // Internal working value
    bool isShared;
    ...

    // set the Variant's type to VARIANT_BOOL
    V_VT(bAllShared) = VT_BOOL;

    // set the value
    V_BOOL(bAllShared) = (isShared ? VARIANT_TRUE : VARIANT_FALSE);

    现在,第二个问题出现在您的示例 VBScript 代码中:
    m_oReportManager.GetReportAccessRights _
    CLng(m_lRptCod), CBool(bAllShared), CBool(bAllRunOnly), CBool(bAllCopy)

    因为您作为参数传递 CBool(something)等,您传递回的是临时变量(CBool​​(...) 的返回值),而不是实际变量 bAllShared等。即使使用正确的 C++ 实现,返回的值也会作为中间值被丢弃。

    您需要像这样调用该方法:
    m_oReportManager.GetReportAccessRights _
    CLng(m_lRptCod), bAllShared, bAllRunOnly, bAllCopy

    那就对了。您不需要“转换”这些值。 VBScript 将始终传递 VARIANT无论你做什么。不用担心,正如我上面所说,即使对于 bool 类型的输入参数等,ATL 也会调用 CBool()。为你。

    (ATL 调用 CBool​​()?那不是一个 VBScript 函数吗?是的,但是 CBool​​() 是一个简单的包装器 VariantChangeType(),这就是 ATL 会为你调用的)

    编辑:
    我忘了提点别的:VBScript 不支持 [out]参数;仅限 [ref]参数。不要将参数声明为 [out]在 C++ 中。如果您的方法声明 [out]参数,VBScript 会像 [ref]参数。这将导致参数的传入值被泄露。如果其中一个 [out] 参数最初是字符串,则该内存将被泄漏;如果它有一个对象,则该对象将永远不会被销毁。

    关于c++ - 将经典 ASP VBScript 参数 ByRef 传递给 COM c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/966767/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com