Creating The VB Wrapper
The
DLL that you created in the last step doesn't export any functions, so
it's useless as a DLL. There are a couple of different ways
to export functions in a DLL, but in order for the functions to
be compatible with VB we need to make sure they're exported in a
specific way, otherwise we would get a "Bad DLL Calling Convention"
error when using the DLL in VB.
C Functions
In
C, a basic function has a return data type, a function name,
and optionally a list of parameters. A basic function named "foo" in C
could look like this
int foo (int bar) { }
The VB equivalent would be
Function foo(bar as long) As Long : : End Function
To make a function export in C so that it is compatible in VB, we need to add the following information,
__declspec(dllexport) WINAPI
The compatible C function would look like
int __declspec(dllexport) WINAPI foo (int bar) { }
vbgamerzip.cpp
Open
(double click) the file vbgamerzip.cpp. If you gave your project a
different name, then this file will have that name. You should see
the following code in the file.
- // vbgamerzip.cpp : Defines the entry point for the DLL application.
- //
- #include "stdafx.h"
- BOOL APIENTRY DllMain( HANDLE hModule,
- DWORD ul_reason_for_call,
- LPVOIDlpReserved
- )
- {
- return TRUE;
- }
This
file will contain all the functions we are going to export. We
aren't creating any new functions, we're simply creating
wrapper functions for a small set of functions that we need for creating
and viewing zip files. Before we start creating our
wrapper functions, we need to include zip.h and unzip.h in this
file.
Depending on where your zlib files are physically
located on the harddrive, either in the same folder as your VC++
project files or in the zlib122 folder or elsewhere will determine how
you need to include the two header files I mentioned.
Since I copied my minizip files to the zlib122 folder, I have the following two lines of code in my project directly under the
#include "stdafx.h" line.
#include "..\zlib122\zip.h"
#include "..\zlib122\unzip.h"If your zip.h and unzip.h files are in your project directory, then you'll only need
#include "zip.h"
#include "unzip.h"After
adding the include statements you should do a test build of your DLL to
make sure your include paths are correct. If you get errors then
you'll need to correct the path or possibly move all the sourcefiles
into the project folder.
Adding The Functions
The first function we're going to add is
crc32. This
function is the only function that's not defined in zip.h
or unzip.h. This function is defined in crc32.c. In the
Zlib Source section, open the crc32.c file. At line 215 you'll
find the function that we need. The first 5 lines look like this:
unsigned long ZEXPORT crc32(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
We're
going to create a similar function in the vbgamerzip.cpp file.
However, our's will be exported and will have a slightly different
return type. VB doesn't have unsigned data types, but it
doesn't really matter in this situation because an "unsignedlong" and a
VB LONG are both 32 bits. This means we can accept values from a C
function, as long as it's 32 bits in size, and store it in a 32bit
variable. The main thing is the size of the variables, not what
they represent. As long as the size of the data isn't changed, we
can store them with no problem.
Since an "unsigned long" is
32 bits and an "int" is 32 bits, we can safely cast the crc32 function to
an "int" data type with no problem. Here is the listing of
the first function we're going to create.
- int __declspec(dllexport) WINAPI VBCRC32 (unsigned long crc,
- constunsigned char FAR*buf,
- unsigned len)
- {
- return crc32(crc, buf, len);
- }
The
function looks a little different. The data types of the paramters
are written with the variable names instead of after the function.
This is simply a personal preference.
If you look at the
function, you'll notice that the function name is "VBCRC32," its return
type is "int" instead of "unsigned long." The parameter list is
exactly the same as the crc32 function. For most of the functions
you can do a copy and paste of the paramter list. The function also has
__declspec(dllexport) WINAPI in the function definition, which lets the compiler know that this function,
VBCRC32, needs to be exported in a VB compatible format.
On
line 5 you can see why this is just a wrapper for
another function. All of the functions we're going to create will
be like this.
Zip.h
The next set of functions are defined in zip.h. We're only going to export 5 functions, here is the list:
- zipOpen2
- zipOpenNewFileInZip3
- zipWriteInFileInZip
- zipCloseFileInZip
- zipClose
The
only odd function in this list in terms of return type
is zipOpen2. It returns a void pointer, so we have to convert
the void pointer to an int in two steps. The other four functions
in the list will all have an "int" return type.
You can open the zip.h file to find the function definitions.
Some
of the functions we're exporting have extra paramters that we don't
really need. If you want a more flexible zip dll, then you'll want
to read through the zlib and minizip source code. Otherwise you
can follow my suggestions here by simplifying the functions.
The function zipOpen2 has a final paramter that is a pointer to a struct of type
zlib_filefunc_def. Since
it's not really needed, we're going to leave it out of our exported
function and simply pass a NULL when calling the wrapped function.
Here is what the final function looks like.
- int __declspec(dllexport) WINAPI VBZipOpen (const char *pathname,
- intappend,
- zipcharpc*globalcomment)
- {
- zipFile z = zipOpen2(pathname, append, globalcomment, NULL);
- return (int)z;
- }
As
you can see, the VBZipOpen function has 3 parameters (pathname, append,
globalcomment), while the zipOpen2 function requires 4 parameters.
If you want access to the 4th paramter, then you'll need to modify the
exported function to include the 4th parameter.
The next
function, zipOpenNewFileInZip3, has a lot of extra paramters that aren't
needed. This function will be simplified a lot. We're going
to use some predefined constants for our function call, as well as pass
a few NULL values for some structs that can complicate our VB code.
NULL Pointers
I'd
like to point out that I'm not blindly passing a "NULL" value
for paramters that I don't need. I've actually read the source
code to these functions, so I know that they can handle situations when
a NULL value is passed intead of the required pointer.
These functions were written to allow these paramters to be optional.
If
you're following along by reading the zip.h file, you'll see
some comments in the file that mention the constants that you need to
use for this function. Other constants may be defined in some of
the zlib files, such as zlib.h, zconf.h, and zutil.h.
The zip
compression technique allows you to specify a compression level or
possibly no compression at all. For this DLL I'm going to usethe
maximum compression level possible. If you want, you can add a
compression parameter to the VB export function, but I've found that I
never use anything other than the maximum.
The final version of
this function is listed below. As you can see the VB export
function has only 5 parameters instead of 16 parameters for the function
it calls.
- int __declspec(dllexport) WINAPI VBZipOpenNewFileInZip(zipFile file,
- constchar* filename,
- constchar* comment,
- constchar* password,
- uLongcrcForCrypting)
- {
- return zipOpenNewFileInZip3(file, filename,
- NULL, NULL, 0, NULL, 0,
- comment,
- Z_DEFLATED,Z_BEST_COMPRESSION, 0,
- -MAX_WBITS,DEF_MEM_LEVEL,Z_DEFAULT_STRATEGY,
- password, crcForCrypting);
- }
The
remaining 3 functions in zip.h are easy to convert so there is no need
to discuss them. The VB names that I used however are
thefollowing:
zipWriteInFileInZip becomes
VBZipWriteFile,
zipCloseFileInZip becomes
VBZipCloseFile,
zipClose becomes
VBZipClose.
Unzip.h
There are 11 functions in unzip.h that we need. Here is the list of functions.
- unzOpen
- unzClose
- unzGetGlobalInfo
- unzGetGlobalComment
- unzGoToFirstFile
- unzGoToNextFile
- unzGetCurrentFileInfo
- unzOpenCurrentFile
- unzOpenCurrentFilePassword
- unzCloseCurrentFile
- unzReadCurrentFile
Just
as zipOpen returned a void pointer, so does unzOpen. It'scast
from a void pointer to an int and is done in a similar way.
None of these functions are simplified, and they're all fairly straight forward.
Here is a complete listing of the vbgamerzip.cpp file.
Code Listing for vbgamerzip.cpp