Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

SafeArray

Status
Not open for further replies.

ilyaw

Programmer
Aug 3, 2006
4
US
Hi, I need help with SafeArray structure, in short I need to import Variant from Excel VBA using dll and change array by reference, I succeeded in bringing array in and working with it, but I do not know how to get back

here is my code:

c++ side:
short __stdcall Single_SafeArray(VARIANT *pv){
int i,j,k;
long lBound,uBound;
HRESULT lResult;
double** new_arr;
long m=0;

//Determine that Variant is an array by testing its type for the VT_ARRAY bit
if((pv->vt|VT_ARRAY)==0)
return (1);

//Determine the array type
VARTYPE vt_type;
if(!pv->parray) return (4);
lResult=SafeArrayGetVartype(pv->parray,&vt_type);
if(lResult!=S_OK) return (2);

//Determine the number of dimensions
int dims = SafeArrayGetDim(pv->parray);
if(dims<1 || dims>2) return(3);

//Get Upper and Lower Bound for each dimensions
int dim_size[MAX_SIZE];
for(i=1;i<=dims;i++){
if(SafeArrayGetLBound(pv->parray,i,&lBound)<0 ||
SafeArrayGetUBound(pv->parray,i,&uBound)<0)
return(4);
//dim_size[0]=rows and dim_size[1]=cols
dim_size[i-1]=uBound-lBound+1;
}

//convert to one dimensional array of doubles
double* arr;
lResult=SafeArrayAccessData(pv->parray,(void**)&arr);
if(lResult!=S_OK) return(5);

//since arr[0]=junk arr[1]=1-st element and so for...by the Way I do not know why?
//and since in VB arrays stored col by col
//initialize new array since my other fnc works with double arrays

new_arr=new double*[dim_size[0]];
for(i=0;i<dim_size[0];i++)
new_arr=new double[dim_size[1]];

for(i=0;i<dim_size[0];i++){
j=2*i+1;
for (k=0;k<dim_size[1];k++){
new_arr[k]=arr[j];
j+=2*dim_size[0];
}
}

//Work with Array
for(i=0;i<dim_size[0];i++){
for(j=0;j<dim_size[1];j++){
new_arr[j]=new_arr[j]+5;
}
}

//Unlock Array
lResult=SafeArrayUnaccessData(pv->parray);
if(lResult!=S_OK) return(5);

//now I need to get back to VB but I stuck , HOW, PLEASE HELP?


vba side:
Private Declare Function Single_SafeArray _
Lib "C:\MyStDll.dll" (ByRef arr As Variant) As Integer

Sub Try_OneDimensionSafeArray()
Dim arr As Variant, k As Integer
Dim arr_rows As Integer, arr_cols As Integer, j As Integer, i As Integer

'Initialize Size of Array
arr = ActiveSheet.Range("target_array").Value
k = Single_SafeArray(arr)
ActiveSheet.Range("return_array").Value = arr
End Sub


thanks

Ilya
 
Please use [ignore]
Code:
[/ignore] tags when posting code.

I'm not sure I understand the problem? What do you mean by getting back to VB? If you're passing the data to the C++ function by reference, shouldn't the modified data be visible in VB when the function ends?
 
I didn't modified the safearray that in the VARIANT structure, I modified the array which points to it using SafeArrayAccessData(pv->parray,(void**)&arr); This is a question how to modify the array within safearray and r=return it.

 
I'm affraid I'm still a bit lost...
Maybe if you explained what you're trying to do with this code and use it for, it might help people understand it better?

One thing I noticed is that in C++ the function returns a short, but in VB it is declared as returning an Integer. You should change the C++ function to return int instead of short.
 
in VB and C++ types have different sizes. in C++ short is the same as VB integer
 
Not really. In C++ a short is 2 bytes (–32,768 to 32,767), while an int is 4 bytes in 32-bit Windows (–2,147,483,648 to 2,147,483,647).
In VB an Integer is 4 bytes (–2,147,483,648 to 2,147,483,647).
 
actually integer in VB is 2 Byte from -32768 to 32767, and what you put in it is long in VB (at least for VB 6.0) it is true. But just believe me it is not the problem, the problem is I do not know how to use SafeArrayPutElement fnc at least it do not work for me.

thanks

Ilya
 
That's strange. In VB 6.0 an Integer is 2 bytes and in .NET it's 4 bytes.

I'm still not sure what your code is trying to do?
If you are trying to pass an array to the function, change the array, then return the changed array back to VB, you could pass 2 arrays by reference. The first would be the input array, and the 2nd would be the output array.
Code:
Single_SafeArray( VARIANT* pInput, VARIANT* pOutput )
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top