Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am getting Error 0x80070057: The parameter is incorrect, from my php script ( run in command line ) . It is calling a COM server I wrote in C#. I also have a C++ client that is working . Please help me find out how to fix the PHP version . I am not sure what is the corret PHP way to pass an SAFEARRAY of strings (BSTR) into the COM function. In the c++ client, DoArray function has this signature: DoArray(SAFEARRAY **). The PHP client reported variant type 8204 by calling variant_get_type($ary). Code 8204 is VT_ARRAY | VT_BSTR , which seems to mean SAFEARRAY of BSTR . It seems strange that I am passing a SAFEARRAY of BSTR and am still getting "The parameter is incorrect" error . I have included PHP com_print_typeinfo for reference . In the output of com_print_typeinfo, I cannot understand what is /* VT_PTR [26] [in] --> VT_SAFEARRAY [27] */ &$ary . I have seen a related PHP bug # 48061 php bug 48061 . Has anyone responded to that bug ?

I am using PHP 5.3.8 (non-thread-safe) for Windows , .NET framework 4 , and Windows 7 .

generated IDL file

// Generated .IDL file (by the OLE/COM Object Viewer)
// 
// typelib filename: FanCom.tlb

[
  uuid(2F0E398B-E218-467D-8B9B-732E24F07780),
  version(1.0),
  custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "FanCom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5066ce5e2963d76a")

]
library FanCom
{
    // TLib :     // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    importlib("mscorlib.tlb");
    // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    dispinterface IFanFan;

    [
      uuid(252B2B91-70FE-4A20-BCF6-3693CE7849D4),
      version(1.0),
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "FanCom.IFanFan")    

    ]
    dispinterface IFanFan {
        properties:
        methods:
            [id(0x60020000)]
            BSTR Echo([in] BSTR str);
            [id(0x60020001)]
            BSTR DoArray([in] SAFEARRAY(BSTR)* ary);
    };

    [
      uuid(0AF61517-E479-4F96-A20E-1D040651C05C),
      version(1.0),
      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "FanCom.FanFan")
    ]
    coclass FanFan {
        interface _Object;
        [default] dispinterface IFanFan;
        [default, source] dispinterface IFanFan;
    };
};

C# COM interop code ( which corresponds to the above IDL code )

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace FanCom
{
    [Guid("252B2B91-70FE-4A20-BCF6-3693CE7849D4")]
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IFanFan
    {
        string Echo(string str);
        string DoArray([In] ref string[] ary);
    }

    [ClassInterface(ClassInterfaceType.None)]           // No ClassInterface
    [ComSourceInterfaces(typeof(IFanFan))]
    [Guid("0AF61517-E479-4F96-A20E-1D040651C05C")]  // CLSID
    [ComVisible(true)]
    public class FanFan : IFanFan
    {
        public string Echo(string str)
        {
            return string.Format("Hello {0}", str);
        }


        public string DoArray(ref string[] ary)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < ary.Length; ++i)
            {
                builder.Append(ary[i]);
                builder.Append(",");
            }
            return builder.ToString();
        }
    }
}

PHP client to use the COM

<?php
echo "started <br/>\n";
$com = new COM("FanCom.FanFan");
echo "com created <br/>\n";
com_print_typeinfo($com);
$s = $com->Echo("Dan");
echo "$s <br/> \n";
//$ary = new VARIANT(array("a", "b", "c") , VT_ARRAY|VT_BSTR);
//$ary = array("a", "b");
//$ary = new VARIANT(array(new VARIANT("a", VT_BSTR), new VARIANT("b", VT_BSTR)), VT_ARRAY|VT_BYREF|VT_BSTR);
//$ary = new VARIANT(array(new VARIANT("a", VT_BSTR), new VARIANT("b", VT_BSTR)), VT_ARRAY|VT_VARIANT);
//$ary = array(new VARIANT("a", VT_BSTR), new VARIANT("b", VT_BSTR));
//$x = new VARIANT(array(new VARIANT("a", VT_BSTR), new VARIANT("b", VT_BSTR)), VT_ARRAY);
//$ary = new VARIANT($x , VT_BYREF|VT_VARIANT);

//$ary = new VARIANT(array('a', 'b') , VT_ARRAY);
//$ary = new VARIANT(array(new VARIANT("a", VT_BSTR), new VARIANT("b", VT_BSTR)), VT_ARRAY);
//$ary = array(new VARIANT("a", VT_BSTR), new VARIANT("b", VT_BSTR));
$ary = new VARIANT(array('a', 'b'), VT_ARRAY);

print variant_get_type($ary);
print "\n";
echo "variant created <br/> \n";
$s1 = $com->DoArray($ary);
echo "$s1 <br/> \n";
echo "end";
?>

php com_print_typeinfo output

class IFanFan { /* GUID={252B2B91-70FE-4A20-BCF6-3693CE7849D4} */
        /* DISPID=1610743808 */
        /* VT_BSTR [8] */
        function Echo(
                /* VT_BSTR [8] [in] */ $str
                )
        {
        }
        /* DISPID=1610743809 */
        /* VT_BSTR [8] */
        function DoArray(
                /* VT_PTR [26] [in] --> VT_SAFEARRAY [27]  */ &$ary
                )
        {
        }
}

C++ client to call the COM

#include <cstdio>
#include <conio.h>
#include "stdafx.h"

#import "C:\Project\FanCom\FanCom\bin\Debug\FanCom.tlb"

#include <oaidl.h>

void CreateSafeArray(SAFEARRAY** saData)        
{
    bstr_t data[3] = {bstr_t(L"a") , bstr_t(L"b") , bstr_t(L"c")  };
    SAFEARRAYBOUND  Bound;
    Bound.lLbound   = 0;
    Bound.cElements = 3;

    *saData = SafeArrayCreate(VT_BSTR, 1 , &Bound);

    BSTR HUGEP *pdFreq;
    HRESULT hr = SafeArrayAccessData(*saData, (void HUGEP* FAR*)&pdFreq);
    if (SUCCEEDED(hr))
    {
        // copy sample values from data[] to this safearray
        for (DWORD i = 0; i < Bound.cElements; ++i)
        {
            *pdFreq++ = data[i].GetBSTR();
        }
        SafeArrayUnaccessData(*saData);
        //SafeArrayUnaccessData(saData);
    }
}

HRESULT ImportCSharpComponent()
{
    HRESULT hr = S_OK;
    ::CoInitialize(NULL);

    try
    {
        FanCom::IFanFanPtr spSimpleObj;
        hr = spSimpleObj.CreateInstance(__uuidof(FanCom::FanFan));
        if (FAILED(hr))
        {
            wprintf(L"FanCom::IFanFanPtr failed w/err 0x%08lx\n", hr);
            return hr;
        }

        {
            bstr_t bstrInput("Derek");
            bstr_t outString = spSimpleObj->Echo(bstrInput);
            wprintf(L"%s\n", (PCWSTR)outString);
        }

        {
            SAFEARRAY* data;
            CreateSafeArray((SAFEARRAY **)&data);
            bstr_t ret = spSimpleObj->DoArray((SAFEARRAY **)&data);
            wprintf(L"DoArray() return %s\n", (PCWSTR)ret);
            SafeArrayDestroy(data);
            data = NULL;
        }

        wprintf(L"\n");
    }
    catch (_com_error &err)
    {
        wprintf(L"The server throws the error: %s\n", err.ErrorMessage());
        wprintf(L"Description: %s\n", (PCWSTR) err.Description());
    }

    // Uninitialize COM for this thread
    ::CoUninitialize();

    return hr;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT h = ImportCSharpComponent();
    return 0;
}
share|improve this question

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.