Introduction
Here in this project we will see how we can call a VC dll from VB. We will see
how to use various VB Variables like byte, integer, long, single, double, string,
currency
. We will also see why to write in VC when VB is an native code compiler.
Well sometimes when we need to call small fast routines C++ is best choice.
But C++ has its own overhead. A typical Visual C++ dll not using MFC can be
40 KB or so (no msvcrt and mfc dll). For a small function this is a very big
overhead. At least 75% is used by CRT (C run time).
I assume reader has comfortable knowledge with C++ and VB. No ATL/MFC knowledge is required.
Now we come to question. How to write super compact super fast DLL for VB.
We will start with ATL. No! No COM!.
Why ATL?
ATL provides its own entry points for the DLL. ATL Entry point is fast
and compact. And thats what we want. Secondly we will never call any CRT functions.
We will always call Windows API functions to minimize the size and speed. Refer
KB Article : Q99456 or see list below.
Eg. see below for string length. In c strlen
but we can call lstrlen
API function. see Here:
void __stdcall ReverseString( BSTR a )
{
int i, iLen;
BSTR b;
LPSTR pA, pB;
#ifdef _UNICODE
iLen = lstrlen( (LPCTSTR) a );
#else
iLen = lstrlen( (LPCSTR) a );
#endif
wow its so easy .
Benefits of Using ATL as a base for a DLL are
- It is compact.
- No CRT burden
- ATL Provides its own entry point so it is easy
- If we do not use ATL DLL then a normal DLL is two to three times big.
Now how to create ATL DLL? It is easy.
Follow these steps
- Select New Project from the file menu.
- Select ATL COM Wizard.
- I do not prefer CRT functions so here is what we see
-
To use CRT select the "Support MFC" check box Like this
- Select "Allow merging of Proxy/Stub code"
ATL has many type of configurations but we are interested mainly in either win32 MIN dependency or win32
unicode min dependency. Note: Unicode is only for Windows NT/2000/XP and
is not supported on Win 95/98/Me.
By using minimum dependency there is no or minimal dependency on any other
dll.
If you have selected Use MFC then in properties select use MFC in static library. It will remove any dependency on MFC DLL's.
Now some small points for writing functions in C++ for use in VB.
- VB uses
__stdcall
so we will also use std calling convention.
- VB does not decorate names like C++ so we have to use extern "C"
- We have to export function names. __declspec(dllexport) is clumsy for VB. As it also decorate function name by using underscore. We will go with def file. Def file is easy. All we have to do is just enter a function name. For example if a function is like this
extern "C" int __stdcall HelloVB( int a) {...}
in the def file we have just write
HelloVB
and VB will recognize our function. If we have used declspec
is could be _HelloVb
Here are VB types and their corresponding types in VC
In VB |
In VC |
Byte |
unsinged char |
Integer |
signed short |
long |
signed long |
single |
float |
double |
double |
currency |
signed __int64 |
string |
BSTR |
So here we will start the DLL. We will use a function for each VB variable.
- First insert a C++ file in our project, then add the following code
extern "c" BYTE __stdcall MakeTripByte( BYTE a, LPBYTE b )
{
*b = a + a;
return( *b + a );
}
extern "c" short __stdcall MakeTripInteger( short a, short *b )
{
*b = a + a;
return( *b + a );
}
extern "c" LONG __stdcall MakeTripLong( long a, long *b )
{
*b = a + a;
return( *b + a );
}
extern "c" float __stdcall MakeTripSingle( float a, float far * b )
{
*b = a + a;
return( *b + a );
}
extern "c" double __stdcall MakeTripDouble( double a, double far * b )
{
*b = a + a;
return( *b + a );
}
extern "c" __int64 __stdcall MakeTripCurrency(__int64 a, __int64 *b)
{
*b = (a + a) ;
return (*b + a);
}
extern "c" void __stdcall ReverseString( BSTR a )
{
int i, iLen;
BSTR b;
LPSTR pA, pB;
#ifdef _UNICODE
iLen = lstrlen( (LPCTSTR) a );
#else
iLen = lstrlen( (LPCSTR) a );
#endif
b = SysAllocStringLen( NULL, iLen );
pA = (LPSTR)a;
pB = (LPSTR)b + iLen -1;
for ( i = 0; i < iLen; i++ )
*pB-- = *pA++;
pA = (LPSTR)a;
pB = (LPSTR)b;
for ( i = 0; i < iLen; i++ )
*pA++ = *pB++;
SysFreeString( b );
}
- Save the file.
- Now select the file tab in the workspace. From there select Source files under name of your project. Then select a file with .def
extension with name of project and in it add the following at the end.
ReverseString
MakeTripByte
MakeTripDouble
MakeTripInteger
MakeTripLong
MakeTripSingle
MakeTripCurrency
- Now select build ->set active configuration to Win32 release min size. Compile the
DLL. Close VC.
- Now start vb
Before copy and pasting code lets see how we will declare our DLL functions in
VB.
[Public | Private] Declare Function_name Lib "libname" [([arglist])] [As type]
Public
or Private
defines scope of function. In forms it is private but in Module it is pub. generally. We will go with private.
Declare
is used to tell vb we are importing a function from DLL.
Then follows name of the function. It is what we typed in our DLL.
then follows lib
with lib name
in quotes. we have to specify the name of
DLL in quotes. It is always better to specify full path. eg. c:\project\dll.dll.
Then follows the argument list. By default VB always passes arguments by reference. So we have to
byref
for pointer arguments and byval
for normal arguments.
The last part determines what a function will return. Refer to the table above.
Now for out above C DLL function declaration will be like this in VB
'enter path for tlb .dll. IF no path given then it is assumed to be in the same folder
Private Declare Function MakeTripByte _
Lib "tvb.dll" ( _
ByVal a As Byte, _
ByRef b As Byte _
) As Byte
Private Declare Function MakeTripInteger _
Lib "tvb.dll" ( _
ByVal a As Integer, _
ByRef b As Integer _
) As Integer
Private Declare Function MakeTripCurrency _
Lib "tvb.dll" ( _
ByVal a As Currency, _
ByRef b As Currency _
) As Currency
Private Declare Function MakeTripLong _
Lib "tvb.dll" ( _
ByVal a As Long, _
ByRef b As Long _
) As Long
Private Declare Function MakeTripSingle _
Lib "tvb.dll" ( _
ByVal a As Single, _
ByRef b As Single _
) As Single
Private Declare Function MakeTripDouble _
Lib "tvb.dll" ( _
ByVal a As Double, _
ByRef b As Double _
) As Double
Private Declare Sub ReverseString _
Lib "tvb.dll" ( _
ByVal a As String _
)
We have done it. All these functions only from a 20K VC DLL with no dependencies and no confusing COM. Please see the project for more details.
List of API functions compared to CRT
Here is list of API functions compared to CRT Win32 Equivalents for C
Run-Time Functions (Q99456)
-------------------------------------------------------------
The information in this article applies to:
Microsoft Win32 Application Programming Interface (API), included with:
the operating system: Microsoft Windows NT, versions 3.1, 3.5, 3.51
Microsoft Windows 95
-------------------------------------------------------------
SUMMARY
Many of the C Run-time functions have direct equivalents in the Win32 application
programming interface (API). This article lists the C Run-time functions by category
with their Win32 equivalents or the word "none" if no equivalent exists.
MORE INFORMATION
NOTE: the functions that are followed by an asterisk (*) are part of the 16-bit C
Run-time only. Functions that are unique to the 32-bit C Run-time are listed separately
in the last section. All other functions are common to both C Run-times.
Buffer Manipulation
_memccpy none
memchr none
memcmp none
memcpy CopyMemory
_memicmp none
memmove MoveMemory
memset FillMemory, ZeroMemory
_swab none
Character Classification
isalnum IsCharAlphaNumeric
isalpha IsCharAlpha, GetStringTypeW (Unicode)
__isascii none
iscntrl none, GetStringTypeW (Unicode)
__iscsym none
__iscsymf none
isdigit none, GetStringTypeW (Unicode)
isgraph none
islower IsCharLower, GetStringTypeW (Unicode)
isprint none
ispunct none, GetStringTypeW (Unicode)
isspace none, GetStringTypeW (Unicode)
isupper IsCharUpper, GetStringTypeW (Unicode)
isxdigit none, GetStringTypeW (Unicode)
__toascii none
tolower CharLower
_tolower none
toupper CharUpper
_toupper none
Directory Control
_chdir SetCurrentDirectory
_chdrive SetCurrentDirectory
_getcwd GetCurrentDirectory
_getdrive GetCurrentDirectory
_mkdir CreateDirectory
_rmdir RemoveDirectory
_searchenv SearchPath
File Handling
_access none
_chmod SetFileAttributes
_chsize SetEndOfFile
_filelength GetFileSize
_fstat See Note 5
_fullpath GetFullPathName
_get_osfhandle none
_isatty GetFileType
_locking LockFileEx
_makepath none
_mktemp GetTempFileName
_open_osfhandle none
remove DeleteFile
rename MoveFile
_setmode none
_splitpath none
_stat none
_umask none
_unlink DeleteFile
Creating Text Output Routines
_displaycursor* SetConsoleCursorInfo
_gettextcolor* GetConsoleScreenBufferInfo
_gettextcursor* GetConsoleCursorInfo
_gettextposition* GetConsoleScreenBufferInfo
_gettextwindow* GetConsoleWindowInfo
_outtext* WriteConsole
_scrolltextwindow* ScrollConsoleScreenBuffer
_settextcolor* SetConsoleTextAttribute
_settextcursor* SetConsoleCursorInfo
_settextposition* SetConsoleCursorPosition
_settextwindow* SetConsoleWindowInfo
_wrapon* SetConsoleMode
Stream Routines
clearerr none
fclose CloseHandle
_fcloseall none
_fdopen none
feof none
ferror none
fflush FlushFileBuffers
fgetc none
_fgetchar none
fgetpos none
fgets none
_fileno none
_flushall none
fopen CreateFile
fprintf none
fputc none
_fputchar none
fputs none
fread ReadFile
freopen (std handles) SetStdHandle
fscanf none
fseek SetFilePointer
fsetpos SetFilePointer
_fsopen CreateFile
ftell SetFilePointer (check return value)
fwrite WriteFile
getc none
getchar none
gets none
_getw none
printf none
putc none
putchar none
puts none
_putw none
rewind SetFilePointer
_rmtmp none
scanf none
setbuf none
setvbuf none
_snprintf none
sprintf wsprintf
sscanf none
_tempnam GetTempFileName
tmpfile none
tmpnam GetTempFileName
ungetc none
vfprintf none
vprintf none
_vsnprintf none
vsprintf wvsprintf
Low-Level I/O
_close _lclose, CloseHandle
_commit FlushFileBuffers
_creat _lcreat, CreateFile
_dup DuplicateHandle
_dup2 none
_eof none
_lseek _llseek, SetFilePointer
_open _lopen, CreateFile
_read _lread, ReadFile
_sopen CreateFile
_tell SetFilePointer (check return value)
_write _lread
Console and Port I/O Routines
_cgets none
_cprintf none
_cputs none
_cscanf none
_getch ReadConsoleInput
_getche ReadConsoleInput
_inp none
_inpw none
_kbhit PeekConsoleInput
_outp none
_outpw none
_putch WriteConsoleInput
_ungetch none
Memory Allocation
_alloca none
_bfreeseg* none
_bheapseg* none
calloc GlobalAlloc
_expand none
free GlobalFree
_freect* GlobalMemoryStatus
_halloc* GlobalAlloc
_heapadd none
_heapchk none
_heapmin none
_heapset none
_heapwalk none
_hfree* GlobalFree
malloc GlobalAlloc
_memavl GlobalMemoryStatus
_memmax GlobalMemoryStatus
_msize* GlobalSize
realloc GlobalReAlloc
_set_new_handler none
_set_hnew_handler* none
_stackavail* none
Process and Environment Control Routines
abort none
assert none
atexit none
_cexit none
_c_exit none
_exec functions none
exit ExitProcess
_exit ExitProcess
getenv GetEnvironmentVariable
_getpid GetCurrentProcessId
longjmp none
_onexit none
perror FormatMessage
_putenv SetEnvironmentVariable
raise RaiseException
setjmp none
signal (ctrl-c only) SetConsoleCtrlHandler
_spawn functions CreateProcess
system CreateProcess
String Manipulation
strcat, wcscat lstrcat
strchr, wcschr none
strcmp, wcscmp lstrcmp
strcpy, wcscpy lstrcpy
strcspn, wcscspn none
_strdup, _wcsdup none
strerror FormatMessage
_strerror FormatMessage
_stricmp, _wcsicmp lstrcmpi
strlen, wcslen lstrlen
_strlwr, _wcslwr CharLower, CharLowerBuffer
strncat, wcsncat none
strncmp, wcsncmp none
strncpy, wcsncpy none
_strnicmp, _wcsnicmp none
_strnset, _wcsnset FillMemory, ZeroMemory
strpbrk, wcspbrk none
strrchr, wcsrchr none
_strrev, _wcsrev none
_strset, _wcsset FillMemory, ZeroMemory
strspn, wcsspn none
strstr, wcsstr none
strtok, wcstok none
_strupr, _wcsupr CharUpper, CharUpperBuffer
MS-DOS Interface
_bdos* none
_chain_intr* none
_disable* none
_dos_allocmem* GlobalAlloc
_dos_close* CloseHandle
_dos_commit* FlushFileBuffers
_dos_creat* CreateFile
_dos_creatnew* CreateFile
_dos_findfirst* FindFirstFile
_dos_findnext* FindNextFile
_dos_freemem* GlobalFree
_dos_getdate* GetSystemTime
_dos_getdiskfree* GetDiskFreeSpace
_dos_getdrive* GetCurrentDirectory
_dos_getfileattr* GetFileAttributes
_dos_getftime* GetFileTime
_dos_gettime* GetSystemTime
_dos_getvect* none
_dos_keep* none
_dos_open* OpenFile
_dos_read* ReadFile
_dos_setblock* GlobalReAlloc
_dos_setdate* SetSystemTime
_dos_setdrive* SetCurrentDirectory
_dos_setfileattr* SetFileAttributes
_dos_setftime* SetFileTime
_dos_settime* SetSystemTime
_dos_setvect* none
_dos_write* WriteFile
_dosexterr* GetLastError
_enable* none
_FP_OFF* none
_FP_SEG* none
_harderr* See Note 1
_hardresume* See Note 1
_hardretn* See Note 1
_int86* none
_int86x* none
_intdos* none
_intdosx* none
_segread* none
Time
asctime See Note 2
clock See Note 2
ctime See Note 2
difftime See Note 2
_ftime See Note 2
_getsystime GetLocalTime
gmtime See Note 2
localtime See Note 2
mktime See Note 2
_strdate See Note 2
_strtime See Note 2
time See Note 2
_tzset See Note 2
_utime SetFileTime
Virtual Memory Allocation
_vfree* See Note 3
_vheapinit* See Note 3
_vheapterm* See Note 3
_vload* See Note 3
_vlock* See Note 3
_vlockcnt* See Note 3
_vmalloc* See Note 3
_vmsize* See Note 3
_vrealloc* See Note 3
_vunlock* See Note 3
32-Bit C Run Time
_beginthread CreateThread
_cwait WaitForSingleObject w/ GetExitCodeProcess
_endthread ExitThread
_findclose FindClose
_findfirst FindFirstFile
_findnext FindNextFile
_futime SetFileTime
_get_osfhandle none
_open_osfhandle none
_pclose See Note 4
_pipe CreatePipe
_popen See Note 4
NOTE 1: The _harderr functions do not exist in the Win32 API. However, much of
their functionality is available through structured exception handling.
NOTE 2: The time functions are based on a format that is not used in Win32. There
are specific Win32 time functions that are documented in the Help file.
NOTE 3: The virtual memory functions listed in this document are specific to the
MS-DOS environment and were written to access memory beyond the 640K of RAM available
in MS-DOS. Because this limitation does not exist in Win32, the standard memory
allocation functions should be used.
NOTE 4: While _pclose() and _popen() do not have direct Win32 equivalents, you can
(with some work) simulate them with the following calls:
_popen CreatePipe
CreateProcess
_pclose WaitForSingleObject
CloseHandle
NOTE 5: GetFileInformationByHandle() is the Win32 equivalent for the _fstat()
C Run-time function. However, GetFileInformationByHandle() is not supported by
Win32s version 1.1. It is supported in Win32s 1.2. GetFileSize(),
GetFileAttributes(), GetFileTime(), and GetFileTitle() are supported by
Win32s 1.1 and 1.2.
Additional query words: 3.10 3.50 4.00
Keywords : kbOSWinNT310 kbOSWinNT350 kbOSWinNT351 kbOSWin95
Issue type :
Technology : kbOSWinNT kbOSWinSearch
Last Reviewed: December 14, 2000
� 2001 Microsoft Corporation. All rights reserved. Terms of Use.
Please visit My Web Site for more tutorials, tweaks, reference.