SafeArray aus VB in einer DLL redimensionieren und mit Daten füllen



  • Hi,

    ich würde gerne ein Array aus Visual Basic an eine C DLL übergeben und dieses Array anschließend in der DLL redimensionieren und mit Daten füllen.

    Momentan versuche ich es mit einem SafeArray, dieses SafeArray lege ich in VB an und übergebe es der DLL, darauf soll die DLL per API Funktion SafeArrayRedim() das Array auf eine bestimmte Größe bringen.

    Allerdings gibt die SafeArrayRedim() Funktion nicht das gewünschte Ergebnis zurück: DISP_E_ARRAYISLOCKED

    Ein zuvor ausgeführtes SafeArrayUnlock() gibt einen UNKNOWN ERROR zurück.

    Option Explicit
    
    ' Dll
    Private Declare Function testDLL Lib "D:\SafeArray ermitteln - DLL\Debug\test.dll" (ByVal PointerToSafeArray As Long) As Long
    ' API
    Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
    
    'Die Bounds für das SafeArray
    Private Type SAFEARRAYBOUND
      cElements As Long
      lLbound As Long
    End Type
    
    'Das SafeArray, eindimensional
    Private Type SAFEARRAY1D
      cDims As Integer
      fFeatures As Integer
      cbElements As Long
      cLocks As Long
      pvData As Long
      Bounds(0 To 0) As SAFEARRAYBOUND
    End Type
    
    'Ausgabe der Struktur
    Private Sub DisplaySafeArray(SA As SAFEARRAY1D)
        Dim H As String
        H = ".cDims = " & SA.cDims & vbCrLf
        H = H & ".fFeatures = " & SA.fFeatures & vbCrLf
        H = H & ".cbElements = " & SA.cbElements & vbCrLf
        H = H & ".cLocks = " & SA.cLocks & vbCrLf
        H = H & ".pvData = " & SA.pvData & vbCrLf
        H = H & ".Bounds(0).cElements = " & SA.Bounds(0).cElements & vbCrLf
        H = H & ".Bounds(0).lLbound = " & SA.Bounds(0).lLbound & vbCrLf
        Text1.Text = H
    End Sub
    
    Private Sub Form_Load()
        Dim lLoop As Long
        Dim MyArray(0) As Long
        Dim SafeArray As SAFEARRAY1D
        Dim PointerToPointer As Long
        Dim PointerToSafeArray As Long
    
        MyArray(0) = 42
    
        'Ersten Zeiger ermitteln
        PointerToPointer = VarPtrArray(MyArray)
    
        'Zweiten Zeiger auslesen
        Call CopyMemory(PointerToSafeArray, ByVal PointerToPointer, 4&)
    
        'SafeArray in vorgegebene Strukur kopieren
        Call CopyMemory(SafeArray, ByVal PointerToSafeArray, Len(SafeArray))
    
        ' DLL aufrufen
        Call testDLL(PointerToSafeArray)
    
        ' SafeArray Infos in VB anzeigen, darunter auch die Größe des Arrays
        Call DisplaySafeArray(SafeArray)
    
        For lLoop = 0 To UBound(MyArray)
            Text1.Text = Text1.Text & vbCrLf & "MyArray[" & lLoop & "] = " & MyArray(lLoop)
        Next lLoop
    
    End Sub
    
    #include "stdafx.h"
    
    BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
    {
        return TRUE;
    }
    
    long __stdcall testDLL(SAFEARRAY* SafeArray)
    {
    	HRESULT hresult;
    
    	SAFEARRAYBOUND SafeArrayBound;
    	SafeArrayBound.cElements = 10;
    	SafeArrayBound.lLbound	 = 0;
    
    	hresult = SafeArrayUnlock(SafeArray);
    
    	if(FAILED(hresult) != 0) return 0;
    
    	hresult = SafeArrayRedim(SafeArray, &SafeArrayBound);
    
    	if(FAILED(hresult) != 0) return 0;
    
          return 1;
    }
    


  • SafeArrays sind zur Parametrisierung im Rahmen vom COM-Servern (DLL/EXE) gedacht. Die Übergabe als Parameter zwischen VB und konventionellenm C++ ist nicht beabsichtigt. Ich schliesse nicht aus das irgendwelche Hacks gibt. Wenn du jedoch zuverlässig Arrays zwischen VB und C++ übergeben willst verwende COM.

    mfg JJ



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Wenn du jedoch zuverlässig Arrays zwischen VB und C++ übergeben willst verwende COM.

    Ähm, hast du dafür vielleicht einen etwas konkreteren Vorschlag oder ein Tutorial parat?



  • Sowas z.B. müsste funktionieren (ungetestet zusammenghackt 😉 )

    Declare Function ArrayUebergabe Lib "einedll.dll" (Byref FirstArrayElement As Long, Byval Length As Long) As Long
    
    Sub Main
        Dim EinLongArray(100) As Long
        Dim ret As Long
        ret = ArrayUebergabe( EinLongArray(0), 100 )
    
    End Sub
    
    extern "C"
    {
    	__declspec(dllexport)  long ArrayUebergabe(long* longArray, long length)
    }
    
    __declspec(dllexport)  long ArrayUebergabe(long* longArray, long length)
    
    {
        for(int i = 0; i < length ; i++ )
        {
            longArray[i] = 100;
        }
        return 0;
    }
    

Log in to reply