Newsgroup: it.comp.lang.visual-basic
Titolo: [OTTISSIMO] prima DLL che gira !

:-((
Coi compilatori Cpp microsoft, e persino col sofisticato visual cpp
integrato in visual studio 6 (che poi ho disinstallato dato che lo volevo
solo provare ma non era "mio") non ero mai riuscito a cavare fuori niente di
funsionante e senza nemmeno capirne la ragione.
Un brindisi metaforico ai prodotti Borland !
Ciao a tutti e scusate lo scoppio di gioia
Soviet-CPP(P)-Mario
eh he he .... bella pure sta firma : CPP .... CPPP (ancora piů plus !)

 funzionato.
Bastava chiedere :)
Oppure cercare in google.
Ciao
--
Math Parser : 
http://www.neodatatype.net
FlowChart   : 
http://www.neodatatype.net/dump/flowchart/dir.asp
Sito Comune : 
http://www.it-lang-vb.net


eh he he .... in apparenza ! In realtà ho spulciato tutti gli help
(abbondanti) e l'MSDN (ampiamente documentato) trovando informazioni diciamo
disorganiche e in nessun luogo complete di tutto. Non avevo trovato una
mappa globale con cui orientarmi e da solo non avevo saputo ricomporre il
puzzle.
Mi dicevano esattamente cosa dovevo fare, soltanto che in nessun luogo si
parlava dell'intero processo e della sequenza per così dire dei comandi.
Ogni singolo dettaglio può andare bene se uno già sa come assemblare le
informazioni da sé, ad esempio perchè con l'esperienza, conosce l'intero
processo nel suo insieme. Io invece non avevo mai potuto coordinare tutte le
varie opzioni ed informazioni. I Wizard-Merda della "mamma" non hanno mai
prodotto una DLL che fungeva, anche se di certo avrebbero potuto, senza che
capissi cosa sbagliavo.
Non fosse stato per le comodissime direttive del CBuilder Borland, che in
pratica consente istruzioni "pass-through" dal codice Cpp direttamente alle
opzioni di riga di comando del compilatore stesso e del LINKER, bypassando e
prevalendo con qualsivoglia default od opzione dei .DEF file e dei .MAK, non
sarei riuscito manco questa volta.
Invece così è comodo anche per uno che non ha esperienza con i vari
"sottoambienti" di un ide complesso, poter settare tutto quanto da codice,
dando esattamente gli ordini che desidera da una unica posizione.
Probabilmente finirò per passare per fazioso sul libro paga della Borland,
ma pazienza. IMHO produce prodotti curati e robusti, spesso senza ridondanze
che non agevolano realmente.
L'unica stronzata, ma tipicamente windowsiana, è stata che il codice basic
INTERPRETATO non cerca le DLL nella directory del codice sorgente del
progetto caricato stesso, ma solo in SYSTEM o WINDOWS (non ricordo).
Forse l'EXE compilato cerca anche sotto il proprio naso, ma l'interpretato
no, chissà perchè. Oppure ancora qualche dettaglio mi sfugge, ma a questo
punto non indago oltre.
Inoltre i messaggi di errore di VB quando carica una DLL sono verdetti da
sibilla cumana.
Mi ha aiutato molto Dependencies Walker (di cui forse avevo letto notizia in
questo stesso NG, cosa di cui ringrazio ancora), che ti dice dove stanare
tutti i vari riferimenti sino in pratica al livello zero del kernel, user,
gdi e advapi.
cmq, eh he he .... d'ora in poi quando mi incaglio in qualche pantano
cross-language VB-Cpp, so a chi chiedere ! ! !
ciao
CPP(P)-Mario


 prodotto una DLL che fungeva
Vorrai dire che fungava, o puffava.



mmm ....
solo una curiosità : ma nella definizione di  WINAPI  è incluso anche il
modificatore di convenzione di chiamata  __stdcall  ?
riassumendo, anche per gli interessati, serve
*** extern "C"  per evitare il name mangling dei nomi di funzione and per
avere linkaggio esterno (dichiarazione e definizione dove si vuole e
visibilità della sub in tutti i file, tipo un super public, o sbaglio ?)
*** __stdcall  (per passare i parametri nell'ordine corretto sullo stack, e
richiedere che lo stack stesso sia pulito dal chiamante .... o dalla
funzione chiamata, non ricordo mai, ma così combacia giusto)
*** __dllexport  per rendere pubblico ed esportabile il nome nella DLL
(sezione export)
veniamo ora ad una domanda per te : ho tentato di fare una callback ma VB va
in crash (nella sua declare il parametro puntatore a funzione ho tentato di
dichiararlo as any, e anche byval as long).
Il resto della DLL funge normalmente, ma quando chiamo la funzione che vuole
il parametro callback (cui da VB passo l'indirizzo di uan routine public di
un modulo standard con <<AddressOf>>) si pianta tutto in modi osceni.
Come posso debuggare una roba simile ? Ho tentato col debugger (sul
disassemblato) ma non capisco un acca dato che il piantamento, as usual, si
verifica nel codice ombra generato da visual basic (e non nel codice che ho
scritto io).
immagino tu abbia già scritto delle callback funzionanti, mi daresti qualche
consiglio generico ?
grazie
Ciao
CCCP-Mario


 dichiararlo as any, e anche byval as long).
Hai provato a dichiararlo byRef?
-- 
Rivolterò il mondo per trovarlo, e anche se andasse in Indocina uno dei 
nostri starà nascosto in una ciotola di riso pronto a sparargli nel culo.
(Pulp Fiction)

Pardon... pensavo ti riferissi a dei parametri passati alla funzione.
Uhm..... AddressOf mi pare che "pretenda" che la funzione di cui pigli 
l'indirizzo si trovi in un modulo.


 visibilità della sub in tutti i file, tipo un super public, o sbaglio ?)
Non è del tutto esatto.
Per prima cosa va precisato che extern "C" va usato *solo* se si sta
scrivendo codice C++, in C è un errore.
Questo serve per indicare al compilatore di seguire le convenzioni di
chiamata delle funzioni (che in C++ sono spesso diverse da quelle del C)
e di non effettuare il name mangling (dovuto ad alcune caratteristiche
del C++ che il C non ha).
L'altro uso di extern (e non di extern "C") del quale tu stai parlano
è la possibilità di indicare al compilatore che una certa variabile è 
solo dichiarata ma è definita in un altro file, anteponendo extern alla 
dichiarazione della variabile stessa (extern int x; per esempio). 
Ciao.
-- 
BSD is for UNIX lovers -- linux is for Windows haters.

 l'indirizzo si trovi in un modulo.
ma infatti se leggi bene il mio post in cui chiedevo, c'è scritto che la
routine era public ed inserita in un modulo standard ....
quanto al byref cosa intendevi ? Byref As Any ? Non è il default ...
ciao
CCCP++Mario


 è la possibilità di indicare al compilatore che una certa variabile è
in realtà ho fatto confusione, mixando entrambi i significati che in effetti
valgono in contesti differenti.
Ciao e grazie delle rettifiche
CCCP++Mario


 consiglio generico ?
Prova a guardare alcune funzioni dell'API che fanno uso di CallBack:
es:
BOOL EnumWindows(
   WNDENUMPROC lpEnumFunc,  // callback function
   LPARAM lParam            // application-defined value
);
quel WNDENUMPROC penso sia un pointer, quindi un intero 32bit.
Vediamo come è usata in VB:
Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, 
ByVal lParam As Long) As Long
E viene chiamata come
EnumWindows AddressOf EnumWindowsProc, ByVal 0&
dove EnumWindowsProc è una funzione che abbia il prototipo che 
EnumWindows si aspetta.
Più in la di così però non so andare (in C++ ho scritto solo qualche 
funzioncina, che spesso ho riscritto in VB per semplicità d'uso).


 ByVal lParam As Long) As Long5555


 }
A parte due errori penso dovuti al ricopiare il codice (il ; mancante ed
un result - minuscolo -spuntato dal nulla), non riesco a capire il
contorto modo di prendere il risultato sia prendendo il valore
restituito dalla funzione che passando un puntatore...


> quanto al byref cosa intendevi ? Byref As Any ? Non è il default ...
No... pensavo (erroneamente) che volessi passare dei parametri ad una 
funzione che accettava puntatori. Allora ti suggerivo di dichiarare i 
parametri come byref.
Es. una funzione (in C) accetta un puntatore ad un array di char, e un 
numero che indica quanti elementi ha questo "array":
__declspec(dllexport) unsigned long int __stdcall foo(char *p, signed 
int nSize)
in VB puoi fare una cosa tipo:
public declare function foo lib "...." (byref S as Byte, byval nSize as 
Integer) as Long;
Dim V(1 to 100) as Byte
foo v(1), 100
Però poi mi sono accorto che non era agli argomenti che ti riferivi...


 restituito dalla funzione che passando un puntatore...
beh, sto testando. LA DLL tal quale non serve a nulla.
Volevo verificare la coerenza del valore di ritorno (in origine erano double
in effetti) con l'argomento modificato via pointer.
Ovvio che la callback non serve a nulla in questo caso e la somma dei
quadrati poteva farla la funzione DLL da sè senza rimpallare a quella VB.
Ma potrebbe servirmi in futuro, e per ora non funge  :_(((
ciao
CCCP++Mario


 in effetti) con l'argomento modificato via pointer.
OK, ma ma usando una sola variabile mette male controllare la
consistenza, dovresti usarne due, una passata per puntatore ed una a cui
assegni il valore di ritorno.
In ogni caso io seguirei il consiglio che ti hanno già dato di non usare
VarPtr ma di dichiarare ByRef il parametro che vuoi passare per
puntatore:
<code>
declare SommaQuadratiDLL lib "MiaLib.DLL" (byval A as Long, byval B as
Long, byref ptrResult as Long, byval PtrFunction as Long) as long
public function SommaViaDLL(byval Op1 as Long, byval Op2 as Long) As
Long
dim SquareSum1 as long
dim SquareSum2 as long
SquareSum1 = SommaQuadratiDLL(Op1, Op2, SquareSum2, AddressOf
SommaInteriVB)
'e qui confronti i due risultati ottenuti
end function
</code>
