Interfacing C functions
VB, VBA, VBScript, JavaScript, are programming languages and scripting languages to write and automate tasks in Office and Windows operating systems. They are easy to implement and good for rapid development. These have API support for doing all sorts of works provided by Windows and Office. Some APIs that are not available in the built-in libraries or some APIs which are custom needed by a user cannot be fulfilled. These types of situations call for a custom-made library file. C programming language does not have any restrictions to access low-layer system calls and utility functions. Thus user requires to implement the required function in C programming and that function can be called from Visual Besic.
VB calls DLL
Visual Basic compiler /linker generates the same type of output binary as of C compiler. Both compilers push arguments from right to left and call the function. Low level machine instructions are the same. So applications written in Visual Basic can access C functions. Functions have to reside inside a dynamic link library(dll). Program loader loads dynamic link library either from current path or from absolute location or searchs all locations given in PATH variable.
VB vs C function prototypes
Apart from dll function address, Visual Basic also need function prototype so that it can push input variables in stack before calling the function. Calling C Functions should be of type stdcall. Stdcall cleans its own stack or callee cleans the stack. So all cleanups are done in Dll side. All Windows DLL works like this. We have below example showing how VB can call a function using call by value and call by reference.
C function prototypes
int extern "C" __stdcall __declspec(dllexport)
CallCByVal
(
char c,
short s,
long l,
float f,
double d,
LPCSTR str
);
int extern "C" __stdcall __declspec(dllexport)
CallCByRef
(
char *c,
short *s,
long *l,
float *f,
double *d,
LPSTR *str
)
VB function prototypes
Public Declare Function CallCByVal Lib "VBDLL.dll"
(
ByVal c As Byte, _
ByVal s As Integer, _
ByVal l As Long, _
ByVal f As Single, _
ByVal d As Double, _
ByVal str As String
) As Integer
Public Declare Function CallCByRef Lib "VBDLL.dll"
(
ByRef c As Byte, _
ByRef s As Integer, _
ByRef l As Long, _
ByRef f As Single, _
ByRef d As Double, _
ByRef str As String
) As Integer
C DLL project
We are creating a Win32 Dynamic Link Library VC++ project. We are selecting this project as Simple Dynamic Link Library Project.
VC++ editor will create the necessary project files including header and C/C++ implementation file.
DllMain() function will be implemented by default by the editor. We need to add CallCByVal, CallCByRef prototypes and the body of the functions.
/* C Windows DLL (VBDLL.dll) Source code */
#include <windows.h>
#include <stdio.h>
BOOL APIENTRY DllMain
(
HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int extern "C" __stdcall __declspec(dllexport)
CallCByVal
(
char c,
short s,
long l,
float f,
double d,
LPCSTR str
)
{
char str_m [100];
sprintf ( str_m,
"Char %c, Short 0x%X, Long %ld,
Float %f, Double %lf, String \"%s\"",
c, (int)s, l, f, d, str);
MessageBoxA(NULL, (const char *)str_m, "Message from C", MB_OK);
return 0;
}
int extern "C" __stdcall __declspec(dllexport)
CallCByRef
(
char *c,
short *s,
long *l,
float *f,
double *d,
LPSTR *str
)
{
char str_m[100];
sprintf ( str_m,
"Char %c, Short 0x%X, Long %ld,
Float %f, Double %lf, String \"%s\"",
*c, (int)*s, *l, *f, *d, *str);
MessageBoxA(NULL, (const char *)str_m, "Values from VB", MB_OK);
*c = *c + 1;
*s = *s + 1;
*l = *l + 1;
*f = *f + 1;
*d = *d + 1;
strcpy(*str,"String from C");
return 0;
}
VB Project
We are creating a simple VB application project to call the C function.
We have added a button in the main form and added the calling code inside the click event of the button.
This is however not limited to VB. VBA, VB script and Javascript can call the function in the same way as VB does.
Public Declare Function CallCByVal Lib "VBDLL.dll"
(
ByVal c As Byte, _
ByVal s As Integer, _
ByVal l As Long, _
ByVal f As Single, _
ByVal d As Double, _
ByVal str As String
) As Integer
Dim c As Byte
Dim i As Integer
Dim l As Long
Dim f As Single
Dim d As Double
Dim s As String
Private Sub Command1_Click()
c = CByte(65)
i = CInt(12)
l = CLng(200)
f = CSng(1.2)
d = CDbl(4.8)
s = CStr("VB String")
Label1.Caption = "Char " + CStr(Chr(c)) + _
", Short " + CStr(i) + _
", Long " + CStr(l) + vbCrLf
Label1.Caption = Label1.Caption + _
"Float " + CStr(f) + _
", Double " + CStr(d) + _
", String " + s
r = CallCByVal(c, i, l, f, f, s)
Label2.Caption = "Char " + CStr(Chr(c)) + _
", Short " + CStr(i) + _
", Long " + CStr(l) + vbCrLf
Label2.Caption = Label2.Caption + _
"Float " + CStr(f) + _
", Double " + CStr(d) + _
", String " + s
End Sub
Public Declare Function CallCByRef Lib "VBDLL.dll"
(
ByRef c As Byte, _
ByRef s As Integer, _
ByRef l As Long, _
ByRef f As Single, _
ByRef d As Double, _
ByRef str As String
) As Integer
Dim c As Byte
Dim i As Integer
Dim l As Long
Dim f As Single
Dim d As Double
Dim s As String
Private Sub Command2_Click()
c = CByte(65)
i = CInt(12)
l = CLng(200)
f = CSng(1.2)
d = CDbl(4.8)
s = CStr("String from VB")
Label1.Caption = "Char " + CStr(Chr(c)) + _
", Short " + CStr(i) + _
", Long " + CStr(l) + vbCrLf
Label1.Caption = Label1.Caption + "Float " + CStr(f) + _
", Double " + CStr(d) + _
", String " + s
r = CallCByRef(c, i, l, f, d, s)
Label2.Caption = "Char " + CStr(Chr(c)) + _
", Short " + CStr(i) + _
", Long " + CStr(l) + vbCrLf
Label2.Caption = Label2.Caption + _
"Float " + CStr(f) + _
", Double " + CStr(d) + _
", String " + s
End Sub
About our authors: Team EQA
You have viewed 1 page out of 27. Your DLL learning is 0.00% complete. Login to check your learning progress.
‹
#
›