Re: Calling ActiveX DLL from MFC - passing arrays
-
Hello, I have created a function in an ActiveX DLL similar to the function below:
Public Function f1(ByRef arr1() As String, ByRef arr2() As Double) As String() End Function
How do I create a SAFEARRAY in Visual C++ to successfully pass both of these arrays?
Regards, Mike
-
Hello, I have created a function in an ActiveX DLL similar to the function below:
Public Function f1(ByRef arr1() As String, ByRef arr2() As Double) As String() End Function
How do I create a SAFEARRAY in Visual C++ to successfully pass both of these arrays?
Regards, Mike
If you put
SafeArray
into CP article search engine, then a bit of magic happens http://www.codeproject.com/info/search.aspx?artkw=SafeArray&sbo=kw[^] :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
[my articles] -
If you put
SafeArray
into CP article search engine, then a bit of magic happens http://www.codeproject.com/info/search.aspx?artkw=SafeArray&sbo=kw[^] :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
[my articles]The data has been put into the SafeArray. However, when reading the data into the VB ActiveX DLL function, I wrote code to display the contents of the array:
Public Function f1(ByRef arr1() As String, ByRef arr2() As Double) As String() ShowList arr1 End Function Private Sub ShowList(ByRef arr() As String) for i1 = LBound(arr, 1) to UBound(arr, 1) MsgBox arr(i1) next i1 End Sub
The program crashes.
Regards, Mike
-
The data has been put into the SafeArray. However, when reading the data into the VB ActiveX DLL function, I wrote code to display the contents of the array:
Public Function f1(ByRef arr1() As String, ByRef arr2() As Double) As String() ShowList arr1 End Function Private Sub ShowList(ByRef arr() As String) for i1 = LBound(arr, 1) to UBound(arr, 1) MsgBox arr(i1) next i1 End Sub
The program crashes.
Regards, Mike
That probably means that
SafeArray
initialization was wrong on the C++ (client) side. How do you perform that task? :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
[my articles] -
That probably means that
SafeArray
initialization was wrong on the C++ (client) side. How do you perform that task? :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
[my articles]SAFEARRAY* CreateASafeArray()
{
//http://www.geocities.com/Jeff\_Louie/safearray.html
USES_CONVERSION; // enables use of ATL conversion macro A2W
char buffer[20]; // used to store ANSI string
HRESULT hr= S_OK;// Create SafeArray of VARIANT BSTRs SAFEARRAY \*pSA; SAFEARRAYBOUND aDim\[1\]; // a one dimensional array aDim\[0\].lLbound= 0; // Visual Basic arrays start with index 0 aDim\[0\].cElements= 10; pSA= SafeArrayCreate(VT\_VARIANT,1,aDim); // create a 1D SafeArray of VARIANTS if (pSA != NULL) { long aLong\[1\]; // iterate over array adding VARIANTs of type VT\_BSTR for (long l= aDim\[0\].lLbound; l< (long)(aDim\[0\].cElements + aDim\[0\].lLbound); l++) { VARIANT vOut; VariantInit(&vOut); vOut.vt= VT\_BSTR; // set type \_ltoa\_s(l,buffer,10); // convert long to ANSI string value vOut.bstrVal= ::SysAllocString(A2W(buffer)); // system wide "new" aLong\[0\]= l; // set index value if (hr= SafeArrayPutElement(pSA, aLong, &vOut)) { // "correctly" copies VARIANT VariantClear(&vOut); // release BSTR from memory on error SafeArrayDestroy(pSA); // does a deep destroy on error return NULL; } VariantClear(&vOut); // does a deep destroy of source VARIANT } // end iteration } return pSA; // clean up here only if you do not return SafeArray as an \[out, retval\] SafeArrayDestroy(pSA); // again does a deep destroy
}
void CaxDlg::OnBnClickedButton1()
{
SAFEARRAY *pSA3 = CreateASafeArray ();
}Regards, Mike
-
SAFEARRAY* CreateASafeArray()
{
//http://www.geocities.com/Jeff\_Louie/safearray.html
USES_CONVERSION; // enables use of ATL conversion macro A2W
char buffer[20]; // used to store ANSI string
HRESULT hr= S_OK;// Create SafeArray of VARIANT BSTRs SAFEARRAY \*pSA; SAFEARRAYBOUND aDim\[1\]; // a one dimensional array aDim\[0\].lLbound= 0; // Visual Basic arrays start with index 0 aDim\[0\].cElements= 10; pSA= SafeArrayCreate(VT\_VARIANT,1,aDim); // create a 1D SafeArray of VARIANTS if (pSA != NULL) { long aLong\[1\]; // iterate over array adding VARIANTs of type VT\_BSTR for (long l= aDim\[0\].lLbound; l< (long)(aDim\[0\].cElements + aDim\[0\].lLbound); l++) { VARIANT vOut; VariantInit(&vOut); vOut.vt= VT\_BSTR; // set type \_ltoa\_s(l,buffer,10); // convert long to ANSI string value vOut.bstrVal= ::SysAllocString(A2W(buffer)); // system wide "new" aLong\[0\]= l; // set index value if (hr= SafeArrayPutElement(pSA, aLong, &vOut)) { // "correctly" copies VARIANT VariantClear(&vOut); // release BSTR from memory on error SafeArrayDestroy(pSA); // does a deep destroy on error return NULL; } VariantClear(&vOut); // does a deep destroy of source VARIANT } // end iteration } return pSA; // clean up here only if you do not return SafeArray as an \[out, retval\] SafeArrayDestroy(pSA); // again does a deep destroy
}
void CaxDlg::OnBnClickedButton1()
{
SAFEARRAY *pSA3 = CreateASafeArray ();
}Regards, Mike
Hello Michael, Your VB object method f1 declared arr1() as of type "string". Your CreateASafeArray() C++ function declared the SAFERRAY as holding elements of type VT_VARIANT. This is the problem : VT_VARIANT type is not a string. VT_BSTR is. To resolve the problem, either : 1. Change the signature of f1 to : Public Function f1(ByRef arr1() As Variant, ByRef arr2() As Double) As String() ShowList arr1 End Function or 2. Change the call to CreateSafeArray() in CreateASafeArray() function to : pSA= SafeArrayCreate(VT_BSTR,1,aDim); // create a 1D SafeArray of VARIANTS and then make the appropriate changes to the rest of the code in CreateASafeArray(). Hope the above suggestions will help you. Best Regards, Bio.
-
Hello Michael, Your VB object method f1 declared arr1() as of type "string". Your CreateASafeArray() C++ function declared the SAFERRAY as holding elements of type VT_VARIANT. This is the problem : VT_VARIANT type is not a string. VT_BSTR is. To resolve the problem, either : 1. Change the signature of f1 to : Public Function f1(ByRef arr1() As Variant, ByRef arr2() As Double) As String() ShowList arr1 End Function or 2. Change the call to CreateSafeArray() in CreateASafeArray() function to : pSA= SafeArrayCreate(VT_BSTR,1,aDim); // create a 1D SafeArray of VARIANTS and then make the appropriate changes to the rest of the code in CreateASafeArray(). Hope the above suggestions will help you. Best Regards, Bio.
-
Bio., Your second piece of advice allowed the string array to be read correctly. Thank you.
Regards, Mike
modified on Thursday, January 10, 2008 11:52:12 AM
Congratulations, Michael. Best wishes to your project. - Bio.