Note that there are some explanatory texts on larger screens.

plurals
  1. POCalling a COM server written in C# and trying to pass a PHP array to a function expecting SAFEARRAY(BSTR)*
    primarykey
    data
    text
    <p>I am getting</p> <pre><code> com_exception: Error [0x80070057] The parameter is incorrect. </code></pre> <p>From my php script ( run in command line ) . It is calling a COM server I wrote in C#. </p> <p>I also have a C++ client that is working. </p> <p>I am not sure what is the correct PHP way to pass a <code>SAFEARRAY</code> of strings (BSTR) into the COM function. </p> <p>In the c++ client, DoArray function has this signature: <code>DoArray(SAFEARRAY **)</code>. The PHP client reported variant type <code>8204</code> by calling <code>variant_get_type($ary)</code>.</p> <p>Code 8204 is <code>VT_ARRAY | VT_BSTR</code> , 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 . </p> <p>I have included PHP <code>com_print_typeinfo()</code> for reference . In the output of <code>com_print_typeinfo</code>, I cannot understand what is </p> <p><code>/* VT_PTR [26] [in] --&gt; VT_SAFEARRAY [27] */ &amp;$ary</code> .</p> <p>I have seen a related PHP bug # 48061 <a href="https://bugs.php.net/bug.php?id=48061" rel="nofollow">php bug 48061</a> . Has anyone responded to that bug ?</p> <p>I am using PHP 5.3.8 (non-thread-safe) for Windows , .NET framework 4 , and Windows 7 .</p> <p>generated IDL file</p> <pre><code>// 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; }; }; </code></pre> <p>C# COM interop code ( which corresponds to the above IDL code )</p> <pre><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 &lt; ary.Length; ++i) { builder.Append(ary[i]); builder.Append(","); } return builder.ToString(); } } } </code></pre> <p>PHP client to use the COM</p> <pre><code>&lt;?php echo "started &lt;br/&gt;\n"; $com = new COM("FanCom.FanFan"); echo "com created &lt;br/&gt;\n"; com_print_typeinfo($com); $s = $com-&gt;Echo("Dan"); echo "$s &lt;br/&gt; \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 &lt;br/&gt; \n"; $s1 = $com-&gt;DoArray($ary); echo "$s1 &lt;br/&gt; \n"; echo "end"; ?&gt; </code></pre> <p>php com_print_typeinfo output</p> <pre><code>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] --&gt; VT_SAFEARRAY [27] */ &amp;$ary ) { } } </code></pre> <p>C++ client to call the COM</p> <pre><code>#include &lt;cstdio&gt; #include &lt;conio.h&gt; #include "stdafx.h" #import "C:\Project\FanCom\FanCom\bin\Debug\FanCom.tlb" #include &lt;oaidl.h&gt; 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 , &amp;Bound); BSTR HUGEP *pdFreq; HRESULT hr = SafeArrayAccessData(*saData, (void HUGEP* FAR*)&amp;pdFreq); if (SUCCEEDED(hr)) { // copy sample values from data[] to this safearray for (DWORD i = 0; i &lt; 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-&gt;Echo(bstrInput); wprintf(L"%s\n", (PCWSTR)outString); } { SAFEARRAY* data; CreateSafeArray((SAFEARRAY **)&amp;data); bstr_t ret = spSimpleObj-&gt;DoArray((SAFEARRAY **)&amp;data); wprintf(L"DoArray() return %s\n", (PCWSTR)ret); SafeArrayDestroy(data); data = NULL; } wprintf(L"\n"); } catch (_com_error &amp;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; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload