Newsgroup: it.comp.lang.visual-basic
Titolo: accessviolation expeption

In 
vb.net
questo è il codice
    Public Declare Function VarptrAny Lib "vb40032.dll" Alias
"VarPtr" (ByVal lpObject As BITMAPINFO) As IntPtr
    Public Declare Function VarPtrAny Lib "vb40032.dll" Alias
"VarPtr" (ByVal lpObject As Bitmap) As IntPtr
    Public Declare Sub GdipCreateBitmapFromGdiDib Lib
"GdiPlus.dll" (ByVal pBIH As IntPtr, ByVal pPix As IntPtr, ByRef
pBitmap As IntPtr)
    Public Sub ArtcFrameProc(ByVal hPlayer As Integer, ByRef pBhi As
BITMAPINFOHEADER, ByRef pFrameDataSrc As Integer, ByVal pUserData As
Integer)
        Dim rgbq As RGBQUAD
        rgbq.rgbBlue = 10
        rgbq.rgbGreen = 10
        rgbq.rgbRed = 10
        rgbq.rgbReserved = 10
        '
        Dim bi As BITMAPINFO
        bi.bmiColors = rgbq
        bi.bmiHeader = pBhi
        Dim MyBitmap As Bitmap
        Dim ptrMybitmap As IntPtr
        Dim PtrBi As IntPtr
        PtrBi = VarPtrAny(bi)
        ptrMybitmap = VarptrAny(MyBitmap)
        Call GdipCreateBitmapFromGdiDib(PtrBi, pFrameDataSrc,
ptrMybitmap)
        '
        Dim realbitmap As Bitmap = Image.FromHbitmap(ptrMybitmap)
        frmLogicSdk.pb1.Image = realbitmap
End Sub
alla chiamata di GdipCreateBitmapFromGdiDib mi genera accessviolation
exeption
Non riesco a capire come mai...
qualcuno me lo saprebbe spiegare?
Se vi serve qualche altra informazione o codice fatemi sapere.
Grazie


Provo ancora a vedere se riesco ad esserti di aiuto.
A me pare che MyBitmap non venga proprio istanziata, cosicché ptrMyBitmap 
punta probabilmente chissà dove... ma poi, le api di vb4 (4!!!) chiamate da 
codice VB2005, dichiarate con lo stesso nome, differente solo per il casing, 
mi spieghi dove le hai trovate?!?!?!?!
Qua c'è un esempio dell'utilizzo dell'api GdipCreateBitmapFromGdiDib, anche 
se in C#, prova a darci un'occhiata, al massimo provo a tradurtelo in VB...
http://www.codeproject.com/KB/GDI-plus/DIBtoBitmap.aspx
Bye
Raf 


gia avevo visto questo esempio, ma non sono stato capace di tradurlo
da c sharp a vb...
Se riesci ad aiutarmi sarebbe grandioso...

 Se riesci ad aiutarmi sarebbe grandioso...
Dovrebbe essere più o meno questa la traduzione (ho recuperato anche le 
dichiarazioni corrette delle strutture e della funzione gdi+):
Imports System.Runtime.InteropServices
Imports System.Reflection
Class DIBUtils
    <DllImport("gdiplus.dll", ExactSpelling:=True)> _
    Friend Shared Function GdipCreateBitmapFromGdiDib( _
        ByVal bminfo As IntPtr, ByVal pixdat As IntPtr, _
        ByRef image As IntPtr) As Integer
    End Function
    <StructLayout(LayoutKind.Sequential, Pack:=2)> _
    Public Class BITMAPINFOHEADER
        Public biSize As Integer
        Public biWidth As Integer
        Public biHeight As Integer
        Public biPlanes As Short
        Public biBitCount As Short
        Public biCompression As Integer
        Public biSizeImage As Integer
        Public biXPelsPerMeter As Integer
        Public biYPelsPerMeter As Integer
        Public biClrUsed As Integer
        Public biClrImportant As Integer
    End Class
    <StructLayout(LayoutKind.Sequential, Pack:=2)> _
    Public Class RGBQUAD
        Public rgbBlue As Byte
        Public rgbGreen As Byte
        Public rgbRed As Byte
        Public rgbReserved As Byte
    End Class
    <StructLayout(LayoutKind.Sequential, Pack:=2)> _
    Public Class BITMAPINFO2
        Public bmiHeader As BITMAPINFOHEADER
        Public bmiColors(1) As RGBQUAD
    End Class
    <StructLayout(LayoutKind.Sequential, Pack:=2)> _
    Public Class BITMAPINFO8
        Public bmiHeader As BITMAPINFOHEADER
        Public bmiColors(255) As RGBQUAD
    End Class
    Public Shared Function BitmapFromDIB(ByVal pDIB As IntPtr, _
        ByVal pPix As IntPtr) As Bitmap
        Dim mi As MethodInfo = _
          GetType(Bitmap).GetMethod("FromGDIplus", _
                BindingFlags.Static Or BindingFlags.NonPublic)
        If mi Is Nothing Then
            Return Nothing ' (permission problem)
        End If
        Dim pBmp As IntPtr = IntPtr.Zero
        Dim Status As Integer = GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp)
        If (Status = 0) AndAlso (pBmp <> IntPtr.Zero) Then ' success
            Return CType(mi.Invoke(Nothing, New Object() {pBmp}), Bitmap)
        Else
            Return Nothing ' failure
        End If
    End Function
End Class
Spero funzioni e che possa aiutarti.
Bye
Raf 

On 24 Giu, 18:38, "Rafunk" <rafunkS...@NOTHANKSlibero.it> wrote:
guarda ho risolto l'accessviolation exeption istanziando il bitmap
come mi dicevi tu, il codice gira... ma non vedo niente.. MANNAGGIA!!!


un ultima domanda su una cosa che non capisco
la funzione la chiamo passandogli in pDIB il puntatore al DIB (e
quello ce l'ho)
in pPix devo passare il puntatore alla alla variabile che contiene la
struttura bitmapinfo....
come faccio dalla struttura ad ottenere il suo puntatore per passarlo
alla funzione?
Grazie

 On 25 Giu, 10:42, "Rafunk" <rafunkS...@NOTHANKSlibero.it> wrote:
[varie]
....
dunque..
prima di tutto grazie mille sei stato nuovamente gentilissimo il tuo
codice gira che è una favola
Il problema è che non vedo niente.... :-( l'immagine continua a non
venire mostrata
       Dim mybitmap As New Bitmap(bi.bmiHeader.biWidth,
bi.bmiHeader.biHeight)
        Dim PtrBi As IntPtr
        PtrBi = VarptrAny(bi)
        mybitmap = DIBUtils.BitmapFromDIB(pFrameDataSrc, PtrBi)
         frmLogicSdk.pb1.Image = mybitmap
        frmLogicSdk.pb1.Refresh()
gira
ma non vedo nulla
:-(

         mybitmap = DIBUtils.BitmapFromDIB(pFrameDataSrc, PtrBi)
Che cos'è bi e da dove proviene?
Che cosa contiene pFrameDataSrc?
Una volta stabilito questo, proviamo a capire come ottenere e passare quei
benedetti puntatori...
Ciao
Raf


ok, scusa, ho evitato di riportare tutto perchè pensavo ricordassi il
post di circa una settimana fa che comprendeva tutto il codice...
pframedatasrc è un puntatore ad un area di memoria unmanaged che
contiene il DIB
bi è la variabile del bitmapinfo
gia ho dato un occhiata alla classe marshal, ma non ho trovato nessun
metodo che mi restituisca un puntatore data una variabile utente come
bitmapinfo, ora do un occhiata anche alla classe gchandle, spero di
trovare qualcosa di utile...
grazie

 bi è la variabile del bitmapinfo
Sì, ho presente, ma mi mancavano (o non mi ricordavo) queste ultime due 
precisazioni.
Prima di tutto vedo che i parametri della chiamata alla BitmapFromDIB vanno 
scambiati (il primo è un ptr a bitmapinfoheader, il secondo un ptr alla 
DIB).
Ora che ci penso, praticamente il codice viene richiamato da una callback 
(unmanaged), in cui ti arrivano proprio quei due puntatori.
Non potrebbe andare bene semplicemente un'implementazione del genere?
    Public Sub ArtcFrameProc(ByVal hPlayer As Integer, ByVal pBIH As IntPtr, 
_
        ByVal pFrameDataSrc As IntPtr, ByVal pUserData As Integer)
        frmLogicSdk.pb1.Image = DIBUtils.BitmapFromDIB(pBIH, pFrameDataSrc)
    End Sub
Bye
Raf 

 Raf
la callback che mi arriva è diversa
è cosi
   Public Sub ArtcFrameProc(ByVal hPlayer As Integer, ByRef pBhi As
BITMAPINFOHEADER, ByRef pFrameDataSrc As IntPtr, ByVal pUserData As
Integer)
come vedi pBhi non è un puntaotre, ma una variabile BITMAPINFOHEADER,
non fare caso al priumo e l'ultimo parametro (hPlayer e pUserData )
che non c'entrano.
Il problema è che DIBUtils.BitmapFromDIB si aspetta due puntatori, uno
al DIB e l'altro alla struttura BITMAPINFOHEADER e io invece ho un
puntatore solo, cioè quello al DIB, di BITMAPINFOHEADER non ho il
puntatore ma il dato e se provo a passarlo alal tua funzione cosi
com'è non funzia perchè lui si aspetta un intptr... ecco perchè avevo
usato l'API varptrany...

 che non c'entrano.
Ok, il prefisso "p" in pBhi che potrebbe avermi ingannato, perň solitamente 
dovrebbe essere indifferente, quando si tratta di puntatori a struttura, 
scrivere "ByRef Param As Struttura" o "ByVal pStruttura As IntPtr"... almeno 
in VB6 era cosě.
Hai per caso un documento di riferimento che spiega l'interfaccia di quella 
callback (presumo sia scritta in C++ unmanaged)?
Altrimenti prova questa versione modificata che usa GCHandle per ricavare il 
ptr a BIH:
Public Sub ArtcFrameProc(ByVal hPlayer As Integer, ByRef BIH As 
BITMAPINFOHEADER, _
    ByRef pFrameDataSrc As IntPtr, ByVal pUserData As Integer)
    ' alloca un handle per impedire al GC di deallocare BIH
    Dim gch As GCHandle = GCHandle.Alloc(BIH, GCHandleType.Pinned)
    ' ottiene l'indirizzo dell'area di memoria managed, per poterlo passare 
ad una funzione unmanaged
    Dim pBIH As IntPtr = gch.AddrOfPinnedObject
    frmLogicSdk.pb1.Image = DIBUtils.BitmapFromDIB(pBIH, pFrameDataSrc)
    ' libera l'handle
    gch.Free()
End Sub
Bye
Raf 


ok dunque...
Ho scoperto che non so perchè, facendo riferimento al form e al
relativo picturebox dall'esterno non visualizzava nemmeno un file bmp
caricato a mano.
Invece caricando il file scrivendo il codice dentor il form l'immagine
veniva mostrata.
Ora ho ripetuto qualche prova, comprese le ultime modifiche che mi hai
segnalato  trasferendo tutto il codice (callback compresa)
direttamente dentro il form, il risultato è che "almeno" vedo un
riquadro nero... e inoltre dopo un po' ricevo sempre ilsolito errore
memoryaccessviolation
Un mio collega mi ha suggerito di provare a caricare il bmp in questo
modo
 pb1.Image = New Bitmap(bi.bmiHeader.biWidth, _
 
bi.bmiHeader.biHeight, _
 
bi.bmiHeader.biWidth * 8 (o quello che è), _
 
Imaging.PixelFormat.Format8bppIndexed, _
 
pFrameDataSrc)
L'ho provato in varie salse e ottengo sempre un riquadro nero anche in
questo modo, certo che se riuscissi a  farlo funzionare cosi mi
libererei da una chiamata esterna ad API, il che non è poco...
tu che ne pensi?
La callback è scritta in c++ unmanaged
Parameters:
    [in] 	hPlayer 	The handle of the player that performs the call.
    [in] 	pBhi 	Pointer to BITMAPINFOHEADER (see External References)
structure information that describes current frame as a Windows DIB.
    [in] 	pFrameDataSrc 	Pointer to frame data (Windows DIB data).
    [in] 	pUserData 	Argument passed to function ArtcPlayerCreate,
when hPlayer is already created.
Returns:
    This function does not return a value.
mi sa che anche in questo caso hai ragione tu, pbhi è un puntatore, ho
provato a modificare la dichiarazione della callback e della delegate
per ricevere un intptr al posto di una variabile bitmapinfo, il
risultato è che quando chiamo la GdipCreateBitmapFromGdiDib (passando
i puntatori direttamente) ho un memoryaccessviolation :-(

 i puntatori direttamente) ho un memoryaccessviolation :-(
Aspetta... ma non č che questo avviene perché la callback viene invocata da 
un thread diverso da quello dell'interfaccia utente (il thread principale)?
Scenario tipico di una DLL C++ che si crea dei worker thread secondari e 
invoca le callback da uno di questi...
In tal caso so che l'accesso ad elementi nel thread principale da un altro 
thread richiede parecchie precauzioni (cross-thread marshaling), pena errori 
di access violation e cross-thread exceptions, ma non ho esperienza diretta 
sull'argomento.
http://msdn.microsoft.com/en-us/magazine/cc188732.aspx
http://p3net.mvps.org/Topics/WinForms/BackgroundWorker.aspx
Ciao
Raf 

 Raf
interessante...
secondo te, se riesco a copiarmi questa area di memoria nella memoria
managed e poi la disegno da un thread gestito....? puo funzionare?
La parte che mi suona piu difficile è il copiarsi questi bit nella
memoria managed...


Credo che occorra usare i delegates e invoke.
Prova a vedere se questo codice funziona:
Nel form frmLogicSdk, aggiungi:
    Delegate Sub SetImage(ByVal Image As System.Drawing.Image)
    Public UpdatePicture As SetImage
    Public Sub SetImageMethod(ByVal Image As System.Drawing.Image)
        pb1.Image = Image
    End Sub
Nella sub New del form aggiungi:
    UpdatePicture = New SetImage(AddressOf SetImageMethod)
Nel punto della routine callback in cui vuoi assegnare l'immagine alla 
picturebox, fai così:
    frmLogicSdk.Invoke(frmLogicSdk.UpdatePicture, 
DIBUtils.BitmapFromDIB(pBIH, pFrameDataSrc))
Ciao
Raf


Solo per curiosità....per mia maledetta curiosità.....
Ma cosa vorresti fare?
Perchè usi le api?...mi sembra che il supporto di net sia abbastanza
completo in fatto di incapsulamento gdi e grafica!...non
capisco!...forse vuoi accedere ad una immagine scannerizzata in
memoria? boh!


wrote:

mi sembra chiaro...
Ho una dll fatta n c++ che mi appoggia un numero variabile di frame
(immagini bitmap in formato DIB a 4CIF) da 25 a a 400 ogni secondo in
una allocazione di memoria, e io le devo mostrare, e devo anche essere
maledettamente veloce per mostrarle tutte senza perderne neanche una,
intanto comunque mi accontenterei di riuscire a mostrarle... visto che
non ci sto riuscendo. inVB6 ce l'avevo fatta, ora lo devo fare in .NET
Prendiamo in considerazione un problema alla volta.
Io devo spostare questo DIB di cui la DLL c++ mi fornisce il puntatore
ad un area di memoria non gestita, lo devo spostare nella memoria
gestita del .NET
Tu come faresti?


System.InvalidOperationException non è stata gestita
  Message="Impossibile chiamare Invoke o BeginInvoke su un controllo
finché non viene creato un handle di finestra."
  Source="System.Windows.Forms"
:-(

 Tu come faresti?
Non lo farei....grazie a Dio non mi viene richiesto!
ma penso che continuerei a farlo in C++....non lo so mica se .NET mi
cattura 400 volte al secondo una immagine!!!
E comunque se volessi farlo in simbiosi con .Net:
Esiste C++/CLI ...se è il tuo pane fare queste cose...dacci un occhio!
un po di link
http://download.microsoft.com/download/b/d/4/bd4a3237-649f-44e2-94db-fd804e01e128/MixedCodeC_CLI.ppt
http://blogs.aspitalia.com/ricciolo/post2167/Interoperabilita-.NET-C-CLI.aspx
http://en.wikipedia.org/wiki/C%2B%2B/CLI
Comunque...se ti vuoi del male....e perseveri su questa strada
http://www.dotnethell.it/articles/WebcamCapture.aspx
guarda un po se riadattando ti è utile (se la dll è fatta bene...è
tutto un giro di PInvoke...azzeccare quello giusto...un altro paio di
maniche!)


È un casino, ho capito... in pratica così facendo accedi all'istanza
predefinita di frmLogicSdk ma da un diverso thread, il che causa il
caricamento di una *nuova* istanza default (diversa da quella nel thread
principale), che evidentemente in quel momento appunto non è ancora
visibile, pertanto ti dà quell'errore.
Credo che forse si possa risolvere così:
    Dim f As frmLogicSdk =  My.Application.OpenForms("frmLogicSdk")
    f.Invoke(f.UpdatePicture, DIBUtils.BitmapFromDIB(pBIH, pFrameDataSrc))
Ciao
Raf