Newsgroup: it.comp.lang.visual-basic
Titolo: [SAFEARRAY] [LUNGO] [AVANZATO] Passaggio di un array da cpp a visual basic, allocazione memoria

Caro NG,
ho un piccolo problemino da sottoporti:
1) ho una dll in cpp che ha una funzione che ritorna un puntatore ad un
buffer di u_char
2) ho una dll scritta da me con una funzione che fa da wrapper _stdcall alla
(1) per passare questo array a visual basic
3) ho il progranmmino vb che riceve i dati dalla (2)
premesso che "TUTTO FUNZIONA" o quanto meno sembra farlo,
avrei una piccola domandina sul modo sporco in cui ho gestito il passaggio:
la funzione (1) è definita così
int read_data( u_char *buffer); //la funzione ritorna la
grandezza del buffer
la mia fuznione wrapper è definita così
long __declspec(dllexport) _stdcall ReadForVB(LPSAFEARRAY FAR
*arr)
in vb è dichiarata così
Public Declare Function ReadForVB Lib "xxxxxx.DLL" (k() As Byte) As
Long
allora:
la cosa migliore da fare sarebbe passare da vb un puntatore ad un array (non
inizializzato) e riempirlo da ReadForVB allocando il safearray e copiando i
dati provenienti da "read_data",
io invece faccio così
----VB---------
dim buff(1) as byte ' inizializzo un array con solo 2 byte ---iquesto mi da
un'array gia inizializzato ma con solo 2 byte
ReadForVb(buff())
----FINE VB---------------------------------
----CPP WRAPPER----------------------
long __declspec(dllexport) _stdcall ReadForVB(LPSAFEARRAY FAR *arr)
int ret;
u_char *data;
ret = read_data(&data); //prendo il buffer
//modifico la struttura del SAFEARRAY prima di ripassarlo a VB
(*arr)-cbElements =ret;
(*arr)-cDims =1;
(*arr)-rgsabound[0].cElements=ret;
(*arr)-rgsabound[0].lLbound =0;
(*arr)-pvData=data; //sostituisco il puntatore ai dati
//secondo me il lavoro è abbastanza sporco, ripeto che funziona alla grande
//ma IMHO fa schifo perchè lascio un buffer di 2byte allocato in memoria e
//non distrutto (i primi due byte allocati in vb)
}
return ret;
}
----------------------CPP WRAPPER
END------------------------------------------
CHE MI DITE , AVETE QUALCHE IDEA MIGLIORE CHE NON SIA UNA DELLE SEGUENTI:
unsigned char *temp;
temp=(unsigned char *)(*arr)-pvData ;
//1) Copy method : For Loop
for (i=0;(i<ret);i++)
temp[i]=data[i];
//2) Copy Method: memcpy
/ memcpy(tempp,data,sizeof(unsigned char)*(ret));
Grazie e ciao
Lorenzo

 Public Declare Function ReadForVB Lib "xxxxxx.DLL" (k() As Byte) As
In effetti giocare con i SAFEARRAY non č il massimo della comoditŕ e della
sicurezza.
Puoi fare cosě (se ho capito bene la domanda):
long __declspec(dllexport) _stdcall ReadForVB(UCHAR *char)
Public Declare Function ReadForVB Lib "xxxxxx.DLL" (ByRef k As Byte) As long
oppure
Public Declare Function ReadForVB Lib "xxxxxx.DLL" (byVal k As Long) As long
La seconda da usare con VarPtr(k(0)) come parametro.
E continui a usare il tutto come array di char (o di byte)
Ciao
--
Math Parser : 
http://www.neodatatype.net
Sito Comune : 
http://www.it-lang-vb.net

 La seconda da usare con VarPtr(k(0)) come parametro.
Ma con questa soluzione , correggimi se sbaglio , devo comunque dichiarare
ed inizializzare l'array in vb
Dim gff(1) as Byte
e non posso usare
Dim gff() as byte
o mi sbaglio?
Grazie per l'aiuto
ciao
Lorenzo

 o mi sbaglio?
No, non sbagli.
Tieni conto che i dati in un SAFEARRAY sono tutti contigui, quindi un array
di byte in VB è sostanzialmente un CHAR* (o un CHAR[] se preferisci e se non
mi sbaglio nella mia ignoranza del C).
Quindi devi per forza avere un array valido.
Un Dim gff() definisce solo l'header del SAFEARRAY ma lasci l'lpvData a null
e quindi è inutile.


Grazie per l'aiuto,
certe volte però mi farebbe piacere un bel punatore puro in vb :P
ciao
lorenzo