SafeArrays in C


Author: Dave
Date: 03.28.16 - 2:23am



They say things come in 3's. So we might as well finish out with a safe array example of returning binary data from C to vb6.

Technically you can use BSTRs for this, I played with it a bit the conversion on the C side was shady, this is better and works fine.

(The testByteArray method would dump it to file and compare it to the md5 of the parent file. Everything checks out.)

Private Declare Function binaryDataTest Lib "teds.dll" (buf() As Byte) As Long
Private Declare Function retSa Lib "teds.dll" () As Byte()

Private Sub Form_Load()
    
    Dim b() As Byte
    
    List1.AddItem "Testing safe array return type.."
    b() = retSa()
    testByteArray b()
    
    Erase b
    
    List1.AddItem "Testing safe array as argument.."
    retval = binaryDataTest(b)
    If retval > 0 Then
        testByteArray b()
    Else
        List1.AddItem "binaryDataTest failed with: " & retval
    End If
    
End Sub





int file_length(FILE *f)
{
	int pos;
	int end;

	pos = ftell (f);
	fseek (f, 0, SEEK_END);
	end = ftell (f);
	fseek (f, pos, SEEK_SET);

	return end;
}

int __stdcall binaryDataTest(SAFEARRAY** psa)
{
#pragma EXPORT
 
	int retVal = 0;
	FILE* fp = fopen("teds.dll", "rb");
	if(fp==0) return 0;	

	int size = file_length(fp);
	unsigned char* dat = (unsigned char*)malloc(size); 

	memset(dat, 0, size);
	fread(dat, 1, size, fp);
	fclose(fp);

	HRESULT hresult = SafeArrayAllocDescriptor(1,psa);
	if( FAILED(hresult)) goto cleanup;

	(*psa)->rgsabound[0].cElements = size;
        (*psa)->cbElements = 1;  

	hresult = SafeArrayAllocData(*psa);
	if( FAILED(hresult) ) goto cleanup;

	for (long i = 0; i < size - 1; i++)
	{
		hresult = SafeArrayPutElement( *psa, &i, (void *)&dat[i] );
		if(FAILED(hresult))	return 0;		
	}
	
	retVal = 1;

cleanup:
	free(dat);
	return  retVal;

}

SAFEARRAY* __stdcall retSa()
{
#pragma EXPORT
 
	FILE* fp = fopen("teds.dll", "rb");
	if(fp==0) return 0;	

	int size = file_length(fp);
	unsigned char* dat = (unsigned char*)malloc(size); 

	memset(dat, 0, size);
	fread(dat, 1, size, fp);
	fclose(fp);

	SAFEARRAYBOUND arrayBounds[1] = { {size, 0}};
	SAFEARRAY* psa = SafeArrayCreate(VT_I1, 1, arrayBounds);
	SafeArrayLock(psa);

	unsigned char* pData = (unsigned char*)(psa->pvData); 

	for (long i = 0; i < size - 1; i++)
	{
		pData[i] = dat[i];	
	}

	free(dat);
	SafeArrayUnlock(psa);
	return psa;

}


One thing I still have to research, what happens if you pass in a safearray that already has data in it? Might have a memleak there, or hit an array lock when trying to realloc its size.




Comments: (0)

 
Leave Comment:
Name:
Email: (not shown)
Message: (Required)
Math Question: 12 + 15 = ? followed by the letter: Q 



About Me
More Blogs
Main Site
Posts: (All)
2020 ( 2 )
2019 ( 5 )
2018 ( 6 )
2017 ( 6 )
2016 (22)
     VB6 CDECL
     UDT Tricks pt2
     Remote Data Extraction
     Collection Extender
     VB6 FindResource
     CDO.Message
     DirList Single Click
     Reset CheckPoint VPN Policy
     VB6 BSTR Oddities Explained
     SafeArrays in C
     BSTR and Variant in C++
     Property let optional args
     Misc Libs
     Enum Named Pipes
     Vb6 Collection in C++
     VB6 Overloaded Methods
     EXPORT FUNCDNAME Warning
     VB6 Syncronous Socket
     Simple IPC
     VB6 Auto Resize Form Elements
     Mach3 Automation
     Exit For in While
2015 ( 16 )
2014 ( 25 )
2013 ( 4 )
2012 ( 10 )
2011 ( 7 )
2010 ( 11 )
2009 ( 3 )