Newsgroup: it.comp.lang.visual-basic
Titolo: Scambio dati tra dll e VB ??

Salve..
Mi sono deciso a scrivere su questo NG perché ho un problema serio che non
riesco a risolvere..
Confido nel vostro aiuto..
Ho un programma in VB, che sto cercando di rendere più veloce riscrivendone
alcune parti in C da linkare come dll..
Ho esguito diverse prove che hanno dato esito positivo, ma quando applico il
tutto al mio programma ottengo sempre un codice che non funziona..
La praticolarità del mio programma in VB é che viene creato un vettore di
grosse dimensioni di tipo "user defined" (ovvero qualche array, qualche
double e qualche integer).
Il vettore subisce qualche redim fino ad un punto in cui inserisco la
chiamata alla dll scritta in C.
Alla dll passo il puntatore del primo elemento dell'array, e poi la dll
esegue dei calcoli sul vettore..
Purtroppo dopo 66508 elementi calcolati bene il programma si pianta a causa
di una violazione di memoria..
Credo che l'errore sia dovuto al fatto che dopo i redim il vettore non
occupi più locazioni sequenziali nella memoria, ma possa risultare
frammentato..
La dll accede al vettore tramite puntatori, pertanto credo che non ci sia
corrispondenza tra istruzioni del tipo " *(vettore+n) = tot " e la reale
posizione degli elementi del vettore creato in ambiente VB..
Sperando di aver spiegato bene il problema.. confido in un vostro aiuto..
Grazie..

Girando su internet ho sentito parlare di safearray..
Pensate possa essere una soluzione?
e se si come?
scusate se rompo..

 in un vostro aiuto..
Se puoi postare il codice VB e quello C è più semplice capire cosa
non funziona.
Ciao.
--
BSD is for UNIX-lovers -- linux is for Windows-haters.

 scusate se rompo..
Per questi problemi si è sempre disponibili (nell'ambito delle nostre
limitate capacità :P)
Ciao

Grazie Zanna..
Adesso vado ad attaccarmi alla cannella del gas :-(
Mi sono fatto un po' di cultura sui safearray, e riadattando alcuni esempi
ho tradotto la dll in modo da implementare i safearray...
Risultato: nonostante il codice sia sensibilmente differente tutto si pianta
nello stesso identico punto con la stessa violazione ad una locazione di
memoria :-(
Il punto in cui si pianta é:
 if(pVettoredatiElements[ccd].Indicatori[Indi] >
pEsperienzaElements[cd].Indicatori[Indi]) Esito++;
Non ci capisco piů nulla.. sta cominciando a diventare veramente dura
pensare di lavorare con una dll su vettori di strutture dati create in VB..
 Di seguito riporto parti di codice, cosě magari provate a darmi un
consiglio..
.. ammesso che esista una soluzione semplice...
In VB ho:
-----------------------------------------
Public Type Vettoredati
    Ro As Double
    Vo As Double
    Indicatori(6) As Double
    Gi As Integer
    Ti As Integer
End Type
Public Type esperienza
    Media As Double
    Dati As Integer
    Indicatori(6) As Double
End Type
Public Declare Function DaiVoti Lib "C:\Documents and
Settings\Stefano\Desktop\Prova\Esperia\Debug\Esperia.dll" (Vettoredati() As
Vettoredati, esperienza() As esperienza) As Long
------------------------------------------
In C.h ho:
------------------------------------------
    /* prototypes */
    #include <windows.h>
    #include <oleauto.h>
typedef struct Vettoredati
{
    double R;
    double V;
    double Indicatori[7];
    int Gi;
    int Ti;
} Vettoredati;
typedef struct Esperienza
{
    double Media;
    int Dati;
    double Indicatori[7];
} Esperienza;
long __declspec (dllexport) __stdcall DaiVoti(SAFEARRAY **psaVettoredati,
SAFEARRAY **psaEsperienza);
------------------------------------------
In C.cpp ho:
------------------------------------------
long __declspec (dllexport) __stdcall DaiVoti(SAFEARRAY **psaVettoredati,
SAFEARRAY **psaEsperienza)
{
int Esito, cd, Indi;
long ccd, Ntot, linea;
HRESULT lResult;
Vettoredati *pVettoredatiElements; // pointer to the elements of the array
Esperienza *pEsperienzaElements; // pointer to the elements of the array
      // how many elements are there in the array
      Ntot=(*psaVettoredati)->rgsabound[0].cElements;
   // how many elements are there in the array
      linea=(*psaEsperienza)->rgsabound[0].cElements;
      // locking the array before using its elements
      lResult=SafeArrayLock(*psaVettoredati);
      if(lResult)return(3);
      // locking the array before using its elements
      lResult=SafeArrayLock(*psaEsperienza);
      if(lResult)return(3);
   // using the array
      pVettoredatiElements=(Vettoredati*) (*psaVettoredati)->pvData;
      // using the array
      pEsperienzaElements=(Esperienza*) (*psaEsperienza)->pvData;
 for(cd= 1; cd <= linea; cd++) {
  for(ccd= 1; ccd <= Ntot; ccd++) {
   Esito = 0;
   for(Indi= 1; Indi <= 6; Indi++) {
    if(pEsperienzaElements[cd].Indicatori[Indi] > 0)
     if(pVettoredatiElements[ccd].Indicatori[Indi] >
pEsperienzaElements[cd].Indicatori[Indi]) Esito++;
    else
     if(pVettoredatiElements[ccd].Indicatori[Indi]
< -pEsperienzaElements[cd].Indicatori[Indi]) Esito++;
   }
   if(Esito=6) pVettoredatiElements[ccd].Vo++;
  }
 }
      // releasing the array
      lResult=SafeArrayUnlock(*psaVettoredati);
      if (lResult) return(4);
      // releasing the array
      lResult=SafeArrayUnlock(*psaEsperienza);
      if (lResult) return(4);
 return(0);
}
------------------------------------------

 In C.cpp ho:
[cut]
Ora è tardi, domani vedo di leggermi il codice e vedere se riesco a
trovare una soluzione, però mi rende curioso una cosa:
perché scrivere codice c++ (file cpp) come se fosse C?


Grazie :-)
Comunque mi sono accorto che nel postare il codice ho commesso un piccolo
errore..
Lo dico perché non vorrei che si vedesse una causa del malfunzionamento in
questo, poiché il codice originario é corretto, a differenza di quanto ho
riportato nel precedente post..
L'errore é in:
typedef struct Vettoredati
{
    double R;
    double V;
Che in in realtà é
typedef struct Vettoredati
{
    double Ro;
    double Vo;
Purtroppo nel trascriverlo ho preso un pezzo di una precedente revisione..
Comunque il malfunzionamento non dipende da questo..
Ciao..

 Vettoredati, esperienza() As esperienza) As Long
Un consiglio veloce (anche se non so se possa essere la causa):
Gli array passali cosě:
Public Declare Function DaiVoti Lib "Esperia.dll" (Vettoredati As
Vettoredati, esperienza As esperienza) As Long
' ^^^ senza le parentesi: passa l'indirizzo del primo elemento.
[...]
Call DaiVoti(VettoreDati(0), Esperienza(0))
E poi ho visto una cosa brutta, anzi... bruttissima :)
In VB gli Integer sono i short int del C!
Se usi int in C (su piattaforme 32 bit) devi usare Long in VB!
Sicuramente questo causa GPF a manetta.
Ciao.

Ho corretto questo errore.. ma non cambia nulla..
Continuano a verificarsi violazioni di accesso..
Se il Vettoredati é lungo 55.000 elementi la dll si pianta quanto va a
leggere circa il 52.000° elelemento
Se il Vettoredati é lungo 69.000 elementi la dll si pianta quanto va a
leggere circa il 59.000° elelemento
Non so da cosa possa dipendere...
Le ho provate tutte...
Sto impazzendo..
Adesso mi viene un dubbio..
Non é che si tratta di VB6 che fa a pugni con WinXP?
I programmi scritti solo in VB mi funzionano bene..
Però adesso ho questo problema che non riesco a risolvere..
Se avete qualche consiglio..
.. vi ringrazio  anticipatamente..


Allora, ti regalo questa perla di saggezza: debugga la DLL C da VC, facendo
partire come programma di debug VB6.
E passa DIECI elementi, non 60000.
Ciaotutti,
*

Vi ringrazio per i consigli che mi avete dato..
Ho risolto..
I problemi erano 2 !!
il primo era  che anche usando int in C e long in VB.. la dimensione dei
dati era diversa..
Ho risolto mettendo in entrambi i linguaggi double al posto di int-long (con
conseguente spreco di memoria)
il secondo era legato all'uso delle parentesi in un if-else statement..
secondo me erano opzionali, ed invece erano obbligatorie :-((( vallo a
capire...
Comunque ora funziona...
5 minuti il tempo di calcolo prima
14 secondi adesso con la nuova dll "splendente" :-)))))

 obbligatorie :-(((
Le parentesi possono essere opzionali, ma non metterle causa
difficoltà di lettura ed errori conseguenti.
